오늘은 gsap를 써서 기.깔. 나는 애니메이션 효과를 한 번 줘보겠습니당.
gsap 애니메이션 효과
기본 구조
<header id="header">
<h1>JJul's PORTFOLIO</h1>
<nav>
<ul>
<li><a href="#">work</a></li>
<li><a href="#">about</a></li>
</ul>
</nav>
</header>
<!-- //header -->
<main id="main">
<div class="text__inner">
<div class="ti1">let's <em>introduce</em></div>
<div class="ti2 split">frontend developer's</div>
<div class="ti3"><em>all</em> works <em>of</em> portfolio</div>
</div>
<div class="img__inner">
<img class="ii1" src="img/figure01.png" alt="이미지1">
<img class="ii2" src="img/figure02.png" alt="이미지2">
<img class="ii3" src="img/figure03.png" alt="이미지3">
</div>
<div id="webgl">
<iframe src="three.html" frameborder="0"></iframe>
</div>
</main>
<!-- //main -->
<footer id="footer">
<a href="https://duektmf34.tistory.com/" target="_blank">BLOG</a>
</footer>
<!-- //footer -->
글씨와 이미지가 순차적으로 나오는 구조로 작업해보겠습니다.
gsap 연동
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
스크립트_글씨 분리하기
일단 글씨를 분리해 애니메이션 효과를 줄 거기 때문에 split를 활용하여 분리해줍니다.
// 글씨 분리하기
document.querySelectorAll(".split").forEach(desc => {
let splitText = desc.innerText;
let splitWrap = splitText.split('').join("</span><span aria-hidden:'true'>");
splitWrap = "<span aria-hidden:'true'>" + splitWrap + "</span>";
desc.innerHTML = splitWrap;
desc.setAttribute("aria-label", splitText);
});
document.querySelectorAll(".split")를 사용하여 HTML 문서 내에서 split 클래스를 가진 모든 요소들을 선택합니다. forEach를 사용하여 각 요소에 대해서 아래 코드를 실행합니다.
splitText 문자열을 각 글자별로 분리한 뒤, 문자열로 연결하여 splitWrap 변수에 저장합니다.
문자열 앞뒤에 <span aria-hidden:'true'>와 </span>을 붙여서 각 글자를 span 요소로 묶어줍니다.
desc 요소의 내용을 splitWrap 변수로 대체합니다.
desc.setAttribute("aria-label", splitText);은 desc 요소의 aria-label 속성에 splitText 값을 할당합니다. 이 속성은 웹 접근성을 위해 스크린 리더 등에서 해당 요소의 읽어주는 문자열로 사용됩니다.
gsap_기본 세팅
// 메인 기본세팅
gsap.set(".text__inner .ti1", {opacity: 0, y: "10vh"});
gsap.set(".text__inner .ti2 span", {opacity: 0, x: 500, scale: 10, display: "inline-block", minWidth: "1.6vw"});
gsap.set(".text__inner .ti3", {opacity: 0, y: "-10vh"});
gsap.set(".img__inner .ii1", {opacity: 0, scale: 5});
gsap.set(".img__inner .ii2", {opacity: 0, scale: 5});
gsap.set(".img__inner .ii3", {opacity: 0, scale: 5});
gsap.set("#header", {y: -100});
gsap.set("#footer", {y: 100});
gsap.set("#webgl", {opacity: 0});
GSAP(TweenMax) 라이브러리를 사용하여 메인 페이지의 기본 설정을 초기화하는 역할을 합니다.
각각의 gsap.set() 메서드를 사용하여 요소들의 초기 스타일을 설정합니다. 예를 들어, .text__inner .ti1 요소는 opacity를 0으로 설정하고, y값을 "10vh"로 설정합니다. 이는 해당 요소가 초기에 화면에서 보이지 않도록 하고, y축으로 10vh 만큼 이동되어 위치를 지정하는 것입니다.
.text__inner .ti2 span 요소는 opacity를 0으로 설정하고, x값을 500으로 설정합니다. 이는 해당 요소가 초기에 보이지 않도록 하고, x축으로 500px 만큼 이동되어 위치를 지정하는 것입니다. 또한, scale 속성을 10으로 설정하여 해당 요소가 나타날 때 크기가 커지도록 설정합니다.
이와 같은 방식으로 .text__inner .ti3, .img__inner .ii1, .img__inner .ii2, .img__inner .ii3, #header, #footer, #webgl 등의 요소들의 초기 스타일을 설정합니다. 이렇게 초기 설정을 해놓으면, 이후에 애니메이션 등에서 이러한 속성들을 변경하여 요소들을 움직이거나 보여주는 등의 효과를 줄 수 있습니다.
gsap_메인 애니메이션
// 메인 애니메이션\
setTimeout(() => {
let tl = gsap.timeline();
tl.to(".text__inner .ti2 span", {opacity: 1, scale: 1, x: 0, duration: 0.6, stagger: 0.1, ease: Power3.easeInOut})
tl.to(".text__inner .ti1", {opacity: 1, y: 0, duration: 0.5, ease: Circ.easOut}, "ee +=0.5")
tl.to(".text__inner .ti3", {opacity: 1, y: 0, duration: 0.5, ease: Circ.easOut}, "ee +=0.5")
tl.to(".img__inner .ii1", {duration: 0.5, opacity: 1, scale: 1, y: "-40vh"}, "+=0.5")
tl.to(".img__inner .ii2", {duration: 0.5, opacity: 1, scale: 1, x: -50, y: "-3vh"}, "+=0.5")
tl.to(".img__inner .ii3", {duration: 0.5, opacity: 1, scale: 1, y: "10vh"}, "+=0.5")
tl.to("#header", {duration: 0.5, y: 0}, "ss +=0.5");
tl.to("#footer", {duration: 0.5, y: 0}, "ss +=0.5");
tl.to("#webgl", {duration: 1, opacity: 1});
}, 3000);
setTimeout() 함수를 사용하여 3초 후에 애니메이션을 실행합니다. 이후 gsap.timeline()을 사용하여 타임라인을 만들고, to() 메서드를 사용하여 각 요소들의 움직임을 지정합니다. 예를 들어, .text__inner .ti2 span 요소는 opacity를 1로 설정하여 보이도록 하고, scale 속성을 1로 설정하여 크기가 원래대로 돌아오도록 하고, x값을 0으로 설정하여 위치가 이동하지 않도록 합니다. 이때 duration 속성은 0.6으로 설정하여 0.6초 동안 애니메이션이 실행되도록 합니다. stagger 속성을 사용하여 요소들의 애니메이션 간격을 조절할 수 있습니다.
완성된 페이지와 코드보기