对象数组中的部分
我试图在这里使用React和GSAP重新创建此代码epen,我一直在尝试重新创建大约一个小时,甚至不知道从哪里开始,请谁能提供帮助。我不想在该代码epen中以相同的方式创建各节,而是想从一系列对象中形成细节,这意味着仅创建一个组件,我对React是一个新手,我想知道如何在React中做类似的事情,从Vanillajs的角度来看它,我已经知道发生了什么,我也在React中这样创建了它,但是我想要一种我的代码最小的情况,并且一系列对象形成一个组件,使其更加动态,以便我可以单击单击在上面获取有关每个部分的更多信息。请协助 下面的Codepen链接
https://codepen.io/design.io/designsignsbyharp/pen/pen/pen/jobpwzg
<div class="slider">
<div class="slider__slide slider__slide--1">
<div class="slider__img slider__img--1"></div>
<div class="slider__text slider__text--1">
<h1 class="slider__header">Rejuvenate your, true self.</h1>
<a href="ign.com" class="cta">discover</a>
</div>
</div>
<div class="slider__slide slider__slide--2">
<div class="slider__img slider__img--2"></div>
<div class="slider__text slider__text--2">
<h1 class="slider__header">Professonial, trust-worthy, and compassionate.</h1>
<a href="google.com" class="cta">learn more</a>
</div>
</div>
<div class="slider__slide slider__slide--3">
<div class="slider__img slider__img--3"></div>
<div class="slider__text slider__text--3">
<h1 class="slider__header">Trust in us.</h1>
<a href="youtube.com" class="cta">learn more</a>
</div>
</div>
<div class="slider__slide slider__slide--4">
<div class="slider__img slider__img--4"></div>
<div class="slider__text slider__text--4">
<h1 class="slider__header">What we do.</h1>
<a href="tsn.ca" class="cta">discover</a>
</div>
</div>
<div class="slider__navigation">
<div class="slider__count slider__count--top">
<p class="count count--top count--top-1">01</p>
<p class="count count--top count--top-2">02</p>
<p class="count count--top count--top-3">03</p>
<p class="count count--top count--top-4">04</p>
</div>
<div class="slider__bar">
<div id="sliderBarDynamic" class="slider__bar--dynamic"></div>
<div class="slider__bar--static"></div>
</div>
<div class="slider__count slider__count--bottom">
<p class="count count--bottom count--bottom-1">02</p>
<p class="count count--bottom count--bottom-2">03</p>
<p class="count count--bottom count--bottom-3">04</p>
<p class="count count--bottom count--bottom-3">01</p>
</div>
</div>
</div>
@import url('https://fonts.googleapis.com/css2?family=Gilda+Display&family=Roboto&display=swap');
*,
*::before,
*::after{
padding:0;
margin:0;
box-sizing:inherit;
}
html{
font-size:16px;
box-sizing:border-box;
}
body{
font-family: 'Roboto', sans-serif;
color:#444444;
font-weight: 300;
line-height: 1.6;
}
img{
max-width:100%;
}
h1{
font-size: 100px;
color: #fff;
font-family: 'Gilda Display', serif;
font-weight: 300;
line-height: 1;
}
h2{
}
h3{
}
P{
color: #fff;
}
a{
text-decoration:none;
color:#ffffff;
font-size: 24px;
}
ul{
list-style-type:none;
}
// Slider
.slider{
width: 100%;
height: 100vh;
overflow: hidden;
position: relative;
&__slide{
width: 100%;
height: 100%;
display: flex;
position: absolute;
top: 0;
left:0;
&--1{
z-index: 4;
}
&--2{
z-index: 3;
}
&--3{
z-index: 2;
}
&--4{
z-index: 1;
}
}
&__img{
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
background-size: cover;
background-repeat: no-repeat;
background-position: 50% 50%;
&--1{
background-image: url('https://i.postimg.cc/Y0T3F1tc/about-landing.jpg');
}
&--2{
background-image: url('https://i.postimg.cc/FHHyKWyf/i-Stock-1148043788.jpg');
}
&--3{
background-image: url('https://i.postimg.cc/tTqp06QH/i-Stock-1064136816.jpg');
}
&--4{
background-image: url('https://i.postimg.cc/435R13K2/i-Stock-1179976698.jpg');
}
}
&__text{
align-self: flex-end;
padding: 0 0 5vw 15vh;
opacity: 0;
width: 80%;
max-width: 1005px;
.slider__header{
margin-bottom: 40px;
text-transform: capitalize;
}
.cta{
font-weight: 700;
text-transform: uppercase;
letter-spacing: 6px;
margin-left: 65px;
position: relative;
&:before{
content: '';
position: absolute;
top: 50%;
transform: translateY(-50%);
left: -55px;
width: 40px;
height: 1px;
background-color: white;
}
}
}
// Slider Navigation
&__navigation{
width: 21px;
height: 400px;
position: fixed;
top: 50%;
transform: translateY(-50%);
left: calc(100% - 5vw);
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
.count--top{
position: absolute;
top: 0;
left: 0;
// position:
}
.count{
opacity: 0;
}
.count:first-child{
opacity: 1;
}
.count--bottom{
position: absolute;
bottom: 0;
left: 0;
}
&__bar{
width: 2px;
height: 250px;
position: relative;
&--dynamic{
width: 100%;
height: 100%;
background-color: #FF69B4;
transform-origin: top center;
position: absolute;
top: 0;
left: 0;
z-index: 2;
}
&--static{
width: 100%;
height: 100%;
background-color: darkgrey;
position: absolute;
top: 0;
left: 0;
}
}
}
// Slider end
/*
*/
// timeline to control animations everytime the timeline restarts/repeats
let tlRepeat = gsap.timeline();
// Need first slides elements - img and text to animate on each repeat of timeline
let repeatBeginning = ()=>{
gsap.set(bgImage[0], {opacity: 0, scale: 1.2, webkitFilter:"blur(" + 6 + "px)"})
tlRepeat
.add("slide1-in")
.fromTo([countTop[0], countBottom[0]], {opacity: 0}, {duration: 0.3, opacity: 1, ease: "Power2.easeIn"}, "slide1-in")
.to(bgImage[0], {duration: 1.8, scale: 1, opacity: 1, webkitFilter:"blur(" + 0 + "px)"}, "slide1-in")
.fromTo(text[0], {opacity: 0, x: -30, ease: "Power2.easeIn"}, {duration: 0.8, opacity: 1, x: 0}, "-=1")
}
// On start animations
// let onStartSlide1Animations = ()=>{
// // gsap.to(text[0], {duration: 0.7, opacity: 1, x: -15, ease: "Power2.easeIn"})
// }
// Variables
let slides = document.querySelectorAll('.slider__slide'),
dynamicBar = document.querySelector('#sliderBarDynamic'),
countTop = document.querySelectorAll(".count--top"),
countBottom = document.querySelectorAll(".count--bottom"),
bgImage = document.querySelectorAll(".slider__img"),
text = document.querySelectorAll(".slider__text"),
tl = gsap.timeline({repeat: 0, delay: 1, paused: false, onRepeat: repeatBeginning});
// Push all text back and only make first one visible
gsap.set(text, {x: -30});
gsap.set(text[0], {opacity: 1});
// Animate slide's elements but not the first one.
// Make first slide's elements animate when timeline is repeating,
// Follow the flow of rest of the slide's animations
slides.forEach((slide, i) =>{
tl
.fromTo(dynamicBar, {scaleY: 0}, {duration: 1.4, scaleY: 1}, "+=2")
.set(dynamicBar, {transformOrigin: "bottom center"})
.to(dynamicBar, {duration: 1, scaleY: 0}, "+=0.4")
.set(dynamicBar, {transformOrigin: "top center"})
.add("elements-in-out")
.to([countTop[i], countBottom[i]], {opacity: 0}, "elements-in-out")
.to([countTop[i+1], countBottom[i+1]], {opacity: 1}, "elements-in-out")
.to(bgImage[i], {duration: 0.2, opacity: 0}, "elements-in-out")
.set(bgImage[i+1], {scale: 1.2, webkitFilter:"blur(" + 6 + "px)"}, "elements-in-out")
.to(bgImage[i+1], {duration: 1.8, scale: 1, webkitFilter:"blur(" + 0 + "px)"}, "elements-in-out")
.to(text[i], {duration: 0.3, opacity: 0}, "elements-in-out")
.to(text[i+1], {duration: 0.8, opacity: 1, x: 0}, "-=1")
})
I am trying to recreate this codepen with react and gsap on here and i have been trying to recreate this for about an hour now and do not even know where to start from, please who can help. i do not want to create the sections the same way in that codepen but rather form the details from an array of objects meaning creating just once component, i am fairly new to react and i would like know how to do something like that in react, looking at it from vanillajs perspective, i already know what is going on and i also created it like this in react but i want a situation where i have minimal code and the an array of objects forms one component making it more dynamic so i can click on it to get more information about each section that comes in. kindly assist
Codepen link below
https://codepen.io/designsbyharp/pen/jObpWZg
HTML
<div class="slider">
<div class="slider__slide slider__slide--1">
<div class="slider__img slider__img--1"></div>
<div class="slider__text slider__text--1">
<h1 class="slider__header">Rejuvenate your, true self.</h1>
<a href="ign.com" class="cta">discover</a>
</div>
</div>
<div class="slider__slide slider__slide--2">
<div class="slider__img slider__img--2"></div>
<div class="slider__text slider__text--2">
<h1 class="slider__header">Professonial, trust-worthy, and compassionate.</h1>
<a href="google.com" class="cta">learn more</a>
</div>
</div>
<div class="slider__slide slider__slide--3">
<div class="slider__img slider__img--3"></div>
<div class="slider__text slider__text--3">
<h1 class="slider__header">Trust in us.</h1>
<a href="youtube.com" class="cta">learn more</a>
</div>
</div>
<div class="slider__slide slider__slide--4">
<div class="slider__img slider__img--4"></div>
<div class="slider__text slider__text--4">
<h1 class="slider__header">What we do.</h1>
<a href="tsn.ca" class="cta">discover</a>
</div>
</div>
<div class="slider__navigation">
<div class="slider__count slider__count--top">
<p class="count count--top count--top-1">01</p>
<p class="count count--top count--top-2">02</p>
<p class="count count--top count--top-3">03</p>
<p class="count count--top count--top-4">04</p>
</div>
<div class="slider__bar">
<div id="sliderBarDynamic" class="slider__bar--dynamic"></div>
<div class="slider__bar--static"></div>
</div>
<div class="slider__count slider__count--bottom">
<p class="count count--bottom count--bottom-1">02</p>
<p class="count count--bottom count--bottom-2">03</p>
<p class="count count--bottom count--bottom-3">04</p>
<p class="count count--bottom count--bottom-3">01</p>
</div>
</div>
</div>
CSS
@import url('https://fonts.googleapis.com/css2?family=Gilda+Display&family=Roboto&display=swap');
*,
*::before,
*::after{
padding:0;
margin:0;
box-sizing:inherit;
}
html{
font-size:16px;
box-sizing:border-box;
}
body{
font-family: 'Roboto', sans-serif;
color:#444444;
font-weight: 300;
line-height: 1.6;
}
img{
max-width:100%;
}
h1{
font-size: 100px;
color: #fff;
font-family: 'Gilda Display', serif;
font-weight: 300;
line-height: 1;
}
h2{
}
h3{
}
P{
color: #fff;
}
a{
text-decoration:none;
color:#ffffff;
font-size: 24px;
}
ul{
list-style-type:none;
}
// Slider
.slider{
width: 100%;
height: 100vh;
overflow: hidden;
position: relative;
&__slide{
width: 100%;
height: 100%;
display: flex;
position: absolute;
top: 0;
left:0;
&--1{
z-index: 4;
}
&--2{
z-index: 3;
}
&--3{
z-index: 2;
}
&--4{
z-index: 1;
}
}
&__img{
width: 100%;
height: 100%;
position: absolute;
z-index: -1;
background-size: cover;
background-repeat: no-repeat;
background-position: 50% 50%;
&--1{
background-image: url('https://i.postimg.cc/Y0T3F1tc/about-landing.jpg');
}
&--2{
background-image: url('https://i.postimg.cc/FHHyKWyf/i-Stock-1148043788.jpg');
}
&--3{
background-image: url('https://i.postimg.cc/tTqp06QH/i-Stock-1064136816.jpg');
}
&--4{
background-image: url('https://i.postimg.cc/435R13K2/i-Stock-1179976698.jpg');
}
}
&__text{
align-self: flex-end;
padding: 0 0 5vw 15vh;
opacity: 0;
width: 80%;
max-width: 1005px;
.slider__header{
margin-bottom: 40px;
text-transform: capitalize;
}
.cta{
font-weight: 700;
text-transform: uppercase;
letter-spacing: 6px;
margin-left: 65px;
position: relative;
&:before{
content: '';
position: absolute;
top: 50%;
transform: translateY(-50%);
left: -55px;
width: 40px;
height: 1px;
background-color: white;
}
}
}
// Slider Navigation
&__navigation{
width: 21px;
height: 400px;
position: fixed;
top: 50%;
transform: translateY(-50%);
left: calc(100% - 5vw);
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
}
.count--top{
position: absolute;
top: 0;
left: 0;
// position:
}
.count{
opacity: 0;
}
.count:first-child{
opacity: 1;
}
.count--bottom{
position: absolute;
bottom: 0;
left: 0;
}
&__bar{
width: 2px;
height: 250px;
position: relative;
&--dynamic{
width: 100%;
height: 100%;
background-color: #FF69B4;
transform-origin: top center;
position: absolute;
top: 0;
left: 0;
z-index: 2;
}
&--static{
width: 100%;
height: 100%;
background-color: darkgrey;
position: absolute;
top: 0;
left: 0;
}
}
}
// Slider end
/*
*/
// timeline to control animations everytime the timeline restarts/repeats
let tlRepeat = gsap.timeline();
// Need first slides elements - img and text to animate on each repeat of timeline
let repeatBeginning = ()=>{
gsap.set(bgImage[0], {opacity: 0, scale: 1.2, webkitFilter:"blur(" + 6 + "px)"})
tlRepeat
.add("slide1-in")
.fromTo([countTop[0], countBottom[0]], {opacity: 0}, {duration: 0.3, opacity: 1, ease: "Power2.easeIn"}, "slide1-in")
.to(bgImage[0], {duration: 1.8, scale: 1, opacity: 1, webkitFilter:"blur(" + 0 + "px)"}, "slide1-in")
.fromTo(text[0], {opacity: 0, x: -30, ease: "Power2.easeIn"}, {duration: 0.8, opacity: 1, x: 0}, "-=1")
}
// On start animations
// let onStartSlide1Animations = ()=>{
// // gsap.to(text[0], {duration: 0.7, opacity: 1, x: -15, ease: "Power2.easeIn"})
// }
// Variables
let slides = document.querySelectorAll('.slider__slide'),
dynamicBar = document.querySelector('#sliderBarDynamic'),
countTop = document.querySelectorAll(".count--top"),
countBottom = document.querySelectorAll(".count--bottom"),
bgImage = document.querySelectorAll(".slider__img"),
text = document.querySelectorAll(".slider__text"),
tl = gsap.timeline({repeat: 0, delay: 1, paused: false, onRepeat: repeatBeginning});
// Push all text back and only make first one visible
gsap.set(text, {x: -30});
gsap.set(text[0], {opacity: 1});
// Animate slide's elements but not the first one.
// Make first slide's elements animate when timeline is repeating,
// Follow the flow of rest of the slide's animations
slides.forEach((slide, i) =>{
tl
.fromTo(dynamicBar, {scaleY: 0}, {duration: 1.4, scaleY: 1}, "+=2")
.set(dynamicBar, {transformOrigin: "bottom center"})
.to(dynamicBar, {duration: 1, scaleY: 0}, "+=0.4")
.set(dynamicBar, {transformOrigin: "top center"})
.add("elements-in-out")
.to([countTop[i], countBottom[i]], {opacity: 0}, "elements-in-out")
.to([countTop[i+1], countBottom[i+1]], {opacity: 1}, "elements-in-out")
.to(bgImage[i], {duration: 0.2, opacity: 0}, "elements-in-out")
.set(bgImage[i+1], {scale: 1.2, webkitFilter:"blur(" + 6 + "px)"}, "elements-in-out")
.to(bgImage[i+1], {duration: 1.8, scale: 1, webkitFilter:"blur(" + 0 + "px)"}, "elements-in-out")
.to(text[i], {duration: 0.3, opacity: 0}, "elements-in-out")
.to(text[i+1], {duration: 0.8, opacity: 1, x: 0}, "-=1")
})
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果我正确理解您的问题,您希望进行更干燥的实现,以便在HTML/JSX中明确编写幻灯片。
收集每张幻灯片之间不同的值,即标题和图像源,将可以在返回中映射的数组中。
示例:
替换映射此
幻灯片
数组的重复JSX。If I'm understanding your question correctly you want a more DRY implementation so the slides are not explicitly written out in HTML/JSX.
Gather up the values that are different between each slide, i.e. the heading and image sources, into an array that can be mapped in the return.
Example:
Replace the repetitive JSX for mapping this
slides
array.