트윈맥스와 스크롤트리거 리액트에서 사용하기
03 Jun 2021 | memo트윈맥스 리액트에서 사용하기
나중에 참고용으로 쓰일 자료라 코드만 복붙해놓겠습니다.
import React, { useRef, useEffect } from 'react';
import styled from 'styled-components';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
import image9 from '../../assets/about-image/9.jpg';
import image10 from '../../assets/about-image/10.jpg';
import image11 from '../../assets/about-image/11.jpg';
import image11_11 from '../../assets/about-image/11-11.jpg';
import image12 from '../../assets/about-image/12.jpg';
import image20 from '../../assets/about-image/20.jpg';
import image21 from '../../assets/about-image/21.jpg';
import image22 from '../../assets/about-image/22.jpg';
import image23 from '../../assets/about-image/23.jpg';
import image24 from '../../assets/about-image/24.jpg';
gsap.registerPlugin(ScrollTrigger);
const Container = styled.div`
overflow-x: hidden;
font-family: 'Quicksand', sans-serif;
`;
const Section = styled.section`
position: relative;
width: 100vw;
&.top {
min-height: 300vh;
.about-contents {
display: flex;
align-items: flex-end;
padding: 1rem;
margin-top: 20rem;
img {
width: 500px;
height: 579px;
}
.about-text {
margin-left: 1rem;
.about-title {
line-height: 90%;
font-weight: bold;
margin-bottom: 1rem;
font-size: 6vw;
}
.about-desc {
margin-top: 3rem;
font-size: 2.5vw;
font-weight: 400;
}
}
}
.title {
position: relative;
color: black;
text-align: center;
padding-top: 20vh;
font-size: 6vw;
font-weight: 400;
div {
display: inline-block;
letter-spacing: -7px;
}
.space {
margin-right: 1rem;
}
}
}
&.bottom {
min-height: 60vh;
.contWrap {
margin: 0 auto;
width: 100%;
max-width: 700px;
ul {
li {
display: inline-block;
margin: 0 2%;
width: 130px;
height: 200px;
border-radius: 6px 6px 6px 6px;
padding: 10px;
cursor: pointer;
p {
font-size: 20px;
color: #fff;
border-bottom: 2px dashed #fff;
}
&:nth-child(1) {
background: linear-gradient(45deg, #f7b733, #fc4a1a);
}
&:nth-child(2) {
background: linear-gradient(45deg, #fc00ff 0%, #401241 100%);
}
&:nth-child(3) {
background-image: linear-gradient(45deg, #ce713b 0%, #f7ce68 100%);
}
&:nth-child(4) {
background-image: linear-gradient(
45deg,
#fa8bff 0%,
#2bd2ff 52%,
#2bff88 90%
);
}
transition: all 1s cubic-bezier(0.075, 0.82, 0.165, 1);
&:hover {
transform: translateY(-20px);
}
}
}
h2 {
text-align: center;
color: black;
margin-top: 30px;
font-weight: 100;
}
}
}
.topBtn {
position: absolute;
bottom: 10%;
right: 70px;
padding: 10px;
border-radius: 6px 6px 6px 6px;
background-color: #eee;
border: 2px solid #eee;
transition: all 0.3s ease-out;
cursor: pointer;
&:hover {
background-color: #000;
border-color: #333;
color: #fff;
}
}
`;
const sections = [
{
title: 'V',
},
{
title: 'I',
},
{
title: 'N',
},
{
title: 'T',
},
{
title: 'A',
},
{
title: 'G',
},
{
title: 'E',
className: 'space',
},
{
title: 'V',
},
{
title: 'E',
},
{
title: 'L',
},
{
title: 'L',
},
{
title: 'A',
},
];
const About = () => {
const titleRef = useRef();
const contentsRefs = useRef([]);
const revealRefs = useRef([]);
revealRefs.current = [];
contentsRefs.current = [];
useEffect(() => {
//스크롤 이벤트
window.addEventListener('scroll', function (event) {
// scrollTop = document.documentElement.scrollTop;
var scroll = window.scrollY;
// starBg.style.transform = 'translateY(' + -scroll / 3 + 'px)';
titleRef.current.style.transform = 'translateY(' + scroll / 1.7 + 'px)';
});
//텍스트 모션
revealRefs.current.forEach((el, index) => {
gsap.from(el, {
autoAlpha: 0,
delay: Math.random() * 1,
ease: 'power3.easeInOut',
});
});
contentsRefs.current.forEach((el, index) => {
gsap.fromTo(
el,
{
autoAlpha: 0,
},
{
duration: 1,
autoAlpha: 1,
ease: 'none',
scrollTrigger: {
id: `section-${index + 1}`,
trigger: el,
start: 'top center+=100',
toggleActions: 'play none none reverse',
},
}
);
});
}, []);
// div들 집어넣음
const addToRefs = (el) => {
if (el && !revealRefs.current.includes(el)) {
revealRefs.current.push(el);
}
};
// about-contents들 집어넣음
const contentsAddToRefs = (el) => {
if (el && !contentsRefs.current.includes(el)) {
contentsRefs.current.push(el);
}
};
return (
<Container>
<Section className='top'>
<h1 className='title' ref={titleRef}>
{sections.map((title, index) => (
<div
ref={addToRefs}
key={index}
className={title.className && 'space'}
>
{title.title}
</div>
))}
</h1>
<div className='about-contents' ref={contentsAddToRefs}>
<img src={image23} alt='' />
<div className='about-text'>
<p className='about-title'>For Your Conscious Closet.</p>
<p className='about-desc'>Sustainable Supply, Selling Ethically.</p>
</div>
</div>
</Section>
<Section className='bottom'>
<div className='contWrap'>
<ul>
<li>
<p>card</p>
</li>
<li>
<p>card</p>
</li>
<li>
<p>card</p>
</li>
<li>
<p>card</p>
</li>
</ul>
<h2>별이 쏟아지는, 인터랙티브</h2>
</div>
<button button='type' className='topBtn'>
TOP
</button>
</Section>
</Container>
);
};
export default About;