GreenSock Animation Platform
μ μ½μλ‘, JavaScript
λ₯Ό μ¬μ©νμ¬ μΉ μ λλ©μ΄μ
μ λ§λ€κΈ° μν κ°λ ₯ν λΌμ΄λΈλ¬λ¦¬μ
λλ€.
gsap.set()
μ μμ±μ μ΄κΈ° μνλ₯Ό μ μνλ λ° μ¬μ©λλ©°, ν΄λΉ μνκ° μ λλ©μ΄μ
μμ΄ μ¦μ μ μ©λ©λλ€.
*μ΄κΈ°κ° μΈν
gsap.to()
λ CSS
μμ±μ νΉμ κ°μΌλ‘ μ λλ©μ΄μ
ννλ λ° μ¬μ©λλ©° λͺ©νκ°μΌλ‘ μμ±μ΄ λ³ννλ μ λλ©μ΄μ
μ μμ±ν©λλ€.
*μ΄νκ° μΈν
gsap.from()
μ μμ±μ νΉμ κ°μμ μμνμ¬ νμ¬ μνλ‘ μ λλ©μ΄μ
ννλ λ° μ¬μ©λλ©° λͺ©νκ°μμ μμκ°μΌλ‘ μμ±μ΄ λ³ννλ μ λλ©μ΄μ
μ μμ±ν©λλ€.
*μ΄μ κ°μΌλ‘ λμκ°
gsap.fromTo()
μμ±μ μμκ° from
μμ λͺ©νκ° to
κΉμ§ μ λλ©μ΄μ
ννλ λ° μ¬μ©λλ©° μμκ°κ³Ό λͺ©νκ°μ λͺ
μμ μΌλ‘ μ€μ νμ¬ μμ±μ΄ λ³ννλ μ λλ©μ΄μ
μ μμ±ν©λλ€.
*μ΄μ κ°(from)μμ μ΄νκ°(to)μΌλ‘
μΌλ ¨μ μ λλ©μ΄μ μ μμ°¨μ λλ λ³λ ¬λ‘ μ€νν μ μλ νμλΌμΈ(Timeline)μ μμ±νλ λ©μλμ λλ€.
timeline .to("#animatedElement", {...},'a') - λΌλ²¨ 'a' .to("#animatedElement", {...},'a+=4') - 'a' 4μ΄ λ€μ μμ
μ λλ©μ΄μ μ νΉμ μ§μ μ μ§μ ν΄ λΌλ²¨λ§ ν¨μΌλ‘ μ λλ©μ΄μ λμμ μμ, μ λλ©μ΄μ μμ μκ° μ§μ λ± νμλΌμΈ λ΄μμ μκ° μ»¨νΈλ‘€μ μ μ°νκ² λ§λ€μ΄ μ€λλ€.
position: sticky
λCSS
μ μμ± μ€ νλλ‘, μ€ν¬λ‘€μ΄ νΉμ μ§μ μ λλ¬νμλ νλ©΄μ κ³ μ μν¬ μ μμ΅λλ€.
μ μ½λμμλ .sticky-element
μ λΆλͺ¨ μμ .container
μ 500vh
λΌλ λμ΄ κ°μ μ£Όμ΄μ μ€ν¬λ‘€μ΄ .container
μ λλ¬νμλ 500vh
μ λμ΄ λ§νΌ .sticky-element
λ₯Ό κ³ μ μν€κ³ μλ λΆλΆμ λ³Ό μ μμ΅λλ€.
ScrollTrigger
λ μ€ν¬λ‘€ μ λλ©μ΄μ μ λ€λ£¨κΈ° μνGSAP
μ νλ¬κ·ΈμΈ μ€ νλλ‘ μ€ν¬λ‘€ μ΄λ²€νΈμ λ°μνμ¬ μμμ μ¬λ¬ μμ±λ€μ μ μ΄ν λ μ¬μ©λ©λλ€.
μ΄λ€ μμκ° ScrollTrigger
λ‘ μ¬μ©λ μ§λ₯Ό μ§μ ν©λλ€.
trigger:'.container' - .container κΈ°μ€μΌλ‘
νΈλ¦¬κ±°μ μ΄λ λΆλΆμμ μ λλ©μ΄μ μ΄ μμνκ³ λλ μ§λ₯Ό μ μν©λλ€.
start:'0% 0%', - "νΈλ¦¬κ±° κΈ°μ€ μλμ° κΈ°μ€" end:'100% 100%' - "νΈλ¦¬κ±° κΈ°μ€ μλμ° κΈ°μ€"
μ λλ©μ΄μ
μ μ§ν μνλ₯Ό μ€ν¬λ‘€λ°μ μ§μ μ°κ²°νμ¬ scrubber
μ²λΌ μλνλλ‘ μ°κ²°ν©λλ€.
scrub: n - nμ΄ λ€μ μ€ν¬λ‘€λ°μ μμΉμ λ°λΌ μ λλ©μ΄μ μ νμ¬ μνκ° μ‘°μ λ©λλ€.
μ λλ©μ΄μ
μ μ΄μ§ easing
μ μ€μ ν©λλ€. μ λλ©μ΄μ
μ΄ μμνκ±°λ μ’
λ£λ λμ μλλ₯Ό μ μ΄νλ λ° μ¬μ©λ©λλ€.
ease:'none' - μ΄μ§ μμ κΈ°
μ€ν¬λ‘€ νΈλ¦¬κ±°μ μμΉλ₯Ό νμΈν λ μ μ©ν λ§μ»€λ₯Ό μΆκ°ν©λλ€.
markers:'true' - λ§μ»€ μΆκ°νκΈ°
νΈλ¦¬κ±°(start)μ μλμ°(start) νΈλ¦¬κ±°κ° λλ¬νμλ μ€νλ©λλ€.
λ°λ λ°©ν₯μΌλ‘ μ€ν¬λ‘€ ν λ μλμ°(end)κ° νΈλ¦¬κ±°(end)μ λλ¬νμλ μ€νλ©λλ€.
νΈλ¦¬κ±°(end)μ μλμ°(end) νΈλ¦¬κ±°κ° λλ¬νμλ μ€νλ©λλ€.
λ°λ λ°©ν₯μΌλ‘ μ€ν¬λ‘€ ν λ μλμ°(start)κ° νΈλ¦¬κ±°(start)μ λλ¬νμλ μ€νλ©λλ€.
ScrollTrigger.create({ trigger:"[data-dark]", start:"0% 55%", end:"100% 40%", toggleClass:{targets:"body",className:"dark"} })
κ²μμ λ°°κ²½μ΄ λ€μ΄κ°λ μμλ€μ <div data-dark="">
λ‘ λ¬Άμ ν "[data-dark]"
λ₯Ό νΈλ¦¬κ±°λ‘ μ§μ νκΈ°
.dark
ν΄λμ€λ₯Ό μμ± (κ²μμ λ°°κ²½, ν°νΈ μμ λ±)
λΆλλ¬μ΄ μμ μ νμ μν΄μ body
μ transition
μΆκ°
body
μ toggleClass
λ₯Ό μ¬μ©νμ¬ start
μ§μ μ λλ¬νμλ ν΄λμ€ .dark
λ₯Ό μΆκ°νκ³ end
μ§μ μ λλ¬νμλμλ ν΄λμ€ .dark
λ₯Ό μ κ±°νλλ‘ λ§λ€κΈ°
gsap.to('.sc-method .method-area',{ scrollTrigger:{ trigger:'.group-method', start:"0% 0%", end:"100% 100%", scrub:0, invalidateOnRefresh: true, }, ease:'none', xPercent:-100, x:function(){ return window.innerWidth; }
μ€ν¬λ‘€νΈλ¦¬κ±°λ₯Ό μ¬μ©ν ν΄λμ€ .group-method
μ νΈλ¦¬κ±°λ₯Ό μ‘κ³ start
/ end
μ§μ μ μ‘μμ£ΌκΈ°
*νΈλ¦¬κ±° start
μ§μ μ¦ 0%
μμ μμνκ³ νΈλ¦¬κ±° end
μ§μ 100%
μμ λλ μ μλλ‘ (start:"0% 0%",end:"100% 100%"
)
invalidateOnRefresh: true
λ₯Ό μ¬μ©νμ¬ λΈλΌμ°μ κ° μλ‘ κ³ μΉ¨λ λ μ€ν¬λ‘€ νΈλ¦¬κ±°λ₯Ό μ΄κΈ°ν μν€κΈ° (μλμ° λ¦¬μ¬μ΄μ§ ν λ μλ‘κ³ μΉ¨ ν μ μλλ‘)
xPercent: -100
μ μ¨μ x
μΆμΌλ‘ -100%
λ§νΌ μ΄λμν€κΈ° (νλ©΄μμ 보μ΄μ§ μκ² λ¨)
x
μ κ°μ ν¨μλ‘ μ€μ νμ¬ x
μ μμΉλ₯Ό window.innerWidth
κ°λ§νΌ x
μΆμΌλ‘ λμμ μ΄λμν€κΈ° (return
ν¨μλ₯Ό μ¨μ μλμ° λ¦¬μ¬μ΄μ§ ν λ μλ‘κ³ μΉ¨ ν μ μκ² λ§λ€κΈ°)
xPercent: -100
μμ window.innerWidth
λ₯Ό λν κ°λ§νΌ μ΄λνμλ λ§μ§λ§ λ΄μ©μ΄ x
μΆκΈ°μ€μΌλ‘ μ κ°μ΄λ°μ μμΉνκ² λ©λλ€.
μΌμͺ½μ μλ μΉ΄λκ° μ μ리μ μλ κ²μ²λΌ 보μ΄μ§λ§
sticky
μ΄νμλ κ³ μ λ κ²μ²λΌ 보μ΄κ² νλ €λ©΄ λ€μsticky
μ μμΉνλ μΉ΄λ μμλ‘ λ°κΏμ£Όμ΄μΌ ν©λλ€.
<div class="sticky-wrapper"> <div class="group-sticky1"> <div class="sticky-inner"> <div class="sticky dataid"> ... </div> </div> </div> <div class="group-sticky2 hide"> <div class="sticky-inner"> <div class="sticky dataid"> ... </div> </div> </div> </div>
.sc-dataid .group-sticky1{ height: 500vh; } .sc-dataid .group-sticky1 .sticky-inner{ height: 600vh; } .sc-dataid .sticky.dataid{ position: sticky; top: 0; height: 100vh; display: flex; overflow: hidden; }
gsap.timeline({ scrollTrigger:{ trigger:'.group-sticky2', start:"0% 0%", end:"100% 100%", scrub:0, onEnter:function(){ $('.sc-dataid .group-sticky1').addClass('hide') $('.sc-dataid .group-sticky2').removeClass('hide') }, onLeaveBack:function(){ $('.sc-dataid .group-sticky1').removeClass('hide') $('.sc-dataid .group-sticky2').addClass('hide') } }, ease:'none' })
sticky
컨ν
μ΄λμΈ .group-sticky1
μ sticky
κ° μ μ©λ .sticky.dataid
μ¬μ΄μ ν΄λμ€.sticky-inner
λ₯Ό μΆκ°νκ³ μ»¨ν
μ΄λλ³΄λ€ 100vh
λ ν° ν¬κΈ°μ λμ΄ κ° μ£ΌκΈ°
.sticky-inner
μ 100vh
λ ν° ν¬κΈ°μ λμ΄ κ°μ μ£Όμμ λ .sticky.dataid
κ° μ»¨ν
μ΄λ λ³΄λ€ 100vh λ§νΌ λ κ³ μ λκ² λκ³ , hide
ν΄λμ€κ° μ μ©λμ΄ μ¨κ²¨μ§ .group-sticky2
κ° κ·Έ μ¬μ΄μ μ¬λΌμ€κ² λ©λλ€.
.group-sticky2
μ onEnter
ν¨μλ₯Ό μ¬μ©ν΄μ μ€ννΈ νΈλ¦¬κ±°μ λλ¬νμλ .group-sticky1
μ hide
ν΄λμ€λ₯Ό λνμ¬ μ¨κΈ°κ³ λ°λλ‘ .group-sticky2
μλ ν΄λμ€λ₯Ό λΉΌμ£ΌκΈ°
onLeaveBack
ν¨μμλ λ°λλ‘ μ μ©νμ¬ μΉ΄λ μμμ Sticky
μ΄νμλ κ³ μ λ κ²μ²λΌ 보μ΄λ ν¨κ³Όλ₯Ό μ€ μ μμ΅λλ€.
<button class="btn-top"> <svg>...</svg> <span class="blind">μλ¨μΌλ‘ μ΄λ</span> </button>
.btn-top{ position: fixed; display: flex; align-items: center; justify-content: center; right: 100px; bottom: 40px; z-index: 2; background-color: #111; width: 50px; height: 50px; opacity: 0; transition: opacity .5s; } .btn-top.change{ position: absolute; bottom: 100.08px; opacity: 1; }
ScrollTrigger.create({ trigger:'.footer', start:"-60.08px 100%", toggleClass:{targets:".btn-top",className:"change"} })
.footer
κΈ°μ€μΌλ‘ μ€ν¬λ‘€ νΈλ¦¬κ±° μ΄λ²€νΈ λ§λ€κΈ° (main
λ³΄λ€ μ»¨νΈλ‘€ νκΈ° μ©μ΄ν¨)
νΈλ¦¬κ±° μ€ννΈ μ§μ μ footer
μμ 60.08px
μ¬λΌκ° μμΉλ‘ μ‘κ³ μλμ° μ€ννΈ μ§μ μ 100%
λ‘ μ‘κΈ°
*60.08px
μ main
λ§μ§λ§ νλ¨μ join us
μ λλ©μ΄μ
μμμ λμ΄λ₯Ό κ³ λ €ν κ°
.btn-top
μ ν΄λμ€ .change
κ° μΆκ°λμμλ CSS
λ§λ€κΈ°
*μλ fixed
μμλλ bottom: 40px
μμΌλ―λ‘ join us
μ λλ©μ΄μ
μ λμ΄λ₯Ό κ³ λ €νμ¬ absolute
μΌλλbottom: 100.08px
λ‘ μμ±