[★] 플러그인
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.12.5/dist/ScrollTrigger.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
# 문제점
애니메이션이 뷰포트 중간에서 시작하고 화면을 벗어나면 초기화하고 싶습니다.
- GSAP는 스크롤트리거의 시작 지점(scroller-start)과 요소의 시작 지점(start)이 만나는 순간 애니메이션이 실행된다.
그리고 애니메이션을 초기화하고 싶을 때 toggleActions을 사용해 요소 위로 스크롤하면 초기화하도록 할 수 있다.
기본적으로 스크롤트리거의 시작 지점은 화면 최하단이라서 문제 되지 않지만 시작 지점을 중간에 둘 경우 toggleActions을 쓰면 아래와 같은 문제가 발생한다.
요소가 아직 화면에 보이는데도 즉시 원상태로 돌아가 버린다.
이 문제는 scrub: true 로도 해결할 수 없다.
# 해결방안
해결 방법은 스크롤트리거를 두 번 사용해야 한다.
하나는 애니메이션이 실행되는 트리거, 다른 하나는 애니메이션이 초기화되는 트리거이다.
[Html]
더보기
<h2>Scroll down</h2>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
[Css]
더보기
<style>
body {
font-family: "Signika Negative", sans-serif;
font-weight: 300;
margin: 0;
padding: 0 20px;
}
h2, .box {
margin-bottom: 100vh;
}
h2 {
text-align: center;
}
.box {
background-color: green;
width: 100px;
height: 100px;
}
</style>
[Script]
더보기
<script>
gsap.registerPlugin(ScrollTrigger);
$(function(){
const boxes = gsap.utils.toArray('.box');
boxes.forEach(box => {
const anim = gsap.to(box, { x: 300, paused: true });
ScrollTrigger.create({
trigger: box,
start: "center 70%",
onEnter: () => anim.play()
});
ScrollTrigger.create({
trigger: box,
start: "top bottom",
onLeaveBack: () => anim.pause(0)
});
});
})
</script>
# 문제점, 해결방안
모바일에서 애니메이션 효과를 사용하고 싶지 않습니다.
[Html]
더보기
<h1>ScrollTrigger.matchMedia() Demo</h1>
<h2>DEPRECATED IN 3.11 IN FAVOUR OF <a href="https://greensock.com/docs/v3/GSAP/gsap.matchMedia()">GSAP.MATCHMEDIA</a></h2>
<section class="gray">
<p>When the viewport is less than 800px, the "Mobile" div will animate. Otherwise, the "Desktop" one will.</p>
<div class="mobile">Mobile</div>
<div class="desktop">Desktop</div>
</section>
<section class="bottom">
<p><strong>Pretty cool, right?</strong></p>
<p>Resize your screen. 800px is the break point. It's all dynamic!</p>
</section>
[Css]
더보기
<style>
body {
color: white;
background-color: black;
text-align: center;
font-weight: 300;
font-family: "Signika Negative", sans-serif, Arial;
}
h1 {
margin: 0;
padding: 35px 10px;
font-size: 40px;
font-weight: 400;
}
.gray {
background: #222;
width: 100%;
height: 100vh;
}
.mobile, .desktop {
width: 200px;
height: 100px;
background: purple;
position: absolute;
z-index: 0;
left: 30%;
top: 50%;
transform: translate3d(-50%, -50%, 0);
text-align: center;
font-size: 1.5em;
font-weight: 400;
line-height: 100px;
color: white;
}
.desktop {
left: 70%;
background: #88ce02;
color: black;
}
.gray p {
color: #ccc;
font-size: 1.4em;
margin: 0;
padding: 30px;
line-height: 1.4em;
}
.bottom {
width: 100%;
color: #ccc;
text-align: center;
padding: 150px 30px;
font-size: 1.5em;
box-sizing: border-box;
}
.bottom strong {
color: white;
}
a {
color: #88ce02;
text-decoration: none;
font-weight: 400;
}
a:hover {
text-decoration: underline;
}
@media (max-width: 799px) {
.mobile, .desktop {
width: 100px;
}
h1 {
font-size: 24px;
}
.gray p {
font-size: 1.2em;
}
}
</style>
[Script]
더보기
<script>
gsap.registerPlugin(ScrollTrigger);
ScrollTrigger.saveStyles(".mobile, .desktop");
ScrollTrigger.matchMedia({
// desktop
"(min-width: 800px)": function() {
let tl = gsap.timeline({
scrollTrigger: {
trigger: ".gray",
scrub: 1,
end: "200%",
pin: true
}
});
tl.to(".desktop", {scale: 2, rotation: 360})
.to(".desktop", {scale: 1});
},
// mobile
"(max-width: 799px)": function() {
let tl = gsap.timeline({
scrollTrigger:{
trigger: ".gray",
scrub: 1,
end: "200%",
pin: true
}
});
tl.to(".mobile", {scale: 2, rotation: 360})
.to(".mobile", {scale: 1});
},
// all
"all": function() {
}
});
</script>
:) 참고링크
티스토리 참고링크