[ScrollMagic] 스크롤매직 라이브러리 - 중급편
기초편에 이어 중급편입니다.
공식 예제 중 ADVANCED에 해당하는 내용을 살펴보겠습니다 :-9
히어뤼고!
1. 섹션 와이프 (매뉴얼)
기초편에서는 단순히 아래에서 위로 올라와 고정되는 와이프였다면,
이번에는 상하좌우에서 슝 날아와 고정되는(?) 섹션 와이프를 구현해봅니다.
구현원리는 간단합니다.
너비높이 100%의 풀페이지 컨테이너를 만든 다음, 얘를 setPin으로 고정시킵니다.
그리고 그 안에 들어갈 여러 개의 섹션을 만들고 absolute 시킵니다.
그 다음에는 섹션의 위치를 -100%로 두었다가, 스크롤 되면 0% 위치로 움직이게 합니다.
여기에 GSAP을 쓰면 짱 편하니까 그렇게 작성합시다ㅋㅋㅋㅋㅋ
우선 마크업을 합니다.
<div id="container">
<section class="panel one">
<b>ONE</b>
</section>
<section class="panel two">
<b>TWO</b>
</section>
<section class="panel three">
<b>THREE</b>
</section>
<section class="panel four">
<b>FOUR</b>
</section>
</div>
CSS도 작성한 다음...
#container {
width: 100%;
height: 100%;
overflow: hidden;
}
.panel {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
font-size: 60px;
text-align: center;
color: #fff;
}
JS를 작성합니다.
var controller = new ScrollMagic.Controller();
var wipeAnimation = new TimelineMax()
.fromTo(".two", 1, {x:"-100%"}, {x:"0%"} )
.fromTo(".three", 1, {y:"-100%"}, {y:"0%"} )
.fromTo(".four", 1, {x:"100%"}, {x:"0%"} )
var scene = new ScrollMagic.Scene({
triggerElement: "#container",
triggerHook: "onLeave",
duration: "500%" //이 값이 클 수록 천천히 덮어씀
})
.setPin("#container")
.setTween(wipeAnimation)
.addIndicators()
.addTo(controller);
Timeline을 통해서, 각 섹션이 -100%에서 0%로 이동하는 걸 볼 수 있습니다.
여기서 체크할 점은, scene에 주어진 duration 값이 크면 클수록 스크롤을 더 많이 해야한다는 것입니다.
달리 말하면 다음 섹션이 더 천천히 스와이프 된다고 할 수도 있죠.
See the Pen ScrollMagic Demo (8) - Dynamic Section Wipe by NY KIM (@nykim_) on CodePen.
2. 섹션 슬라이드
이 다음은 섹션 슬라이드입니다. 위의 예제와 비슷하긴 하지만 좀 더 다이내-믹!한 효과를 줘보겠습니다.
원리는 동일합니다. container를 고정시키고, 섹션이 움직이도록 애니메이션을 설정하면 됩니다.
먼저 마크업입니다.
<div id="pinContainer">
<div id="slideContainer">
<section class="panel one">
<b>ONE</b>
</section>
<section class="panel two">
<b>TWO</b>
</section>
<section class="panel three">
<b>THREE</b>
</section>
<section class="panel four">
<b>FOUR</b>
</section>
</div>
</div>
아까와는 다르게 컨테이너가 두 개인 구조입니다.
pinContainer는 고정하고, slideContainer의 위치만 움직일 거에요.
#pinContainer {
width: 100%;
height: 100%;
overflow: hidden;
-webkit-perspective: 1000;
perspective: 1000;
}
#slideContainer {
width: 400%;// 100*4 slides
height: 100%;
}
.panel {
float: left;
width: 25%; // 400/25 = 100%
height: 100%;
font-size: 60px;
text-align: center;
color: #fff;
}
따라서 slideContainer는 100%*4개 섹션 = 400%만큼의 너비를 주고,
각 섹션은 그 25%의 너비를 갖도록 합니다.
그리고 자바스크립트를 작성합니다.
var controller = new ScrollMagic.Controller();
var wipeAnimation = new TimelineMax()
// animate to second
.to("#slideContainer", 1, { z: -180 })
.to("#slideContainer", 1, { x: "-25%" })
.to("#slideContainer", 1, { z: 0 })
// animate to third
.to("#slideContainer", 1, { z: -180, delay: 0.6 })
.to("#slideContainer", 1, { x: "-50%" })
.to("#slideContainer", 1, { z: 0 })
// animate to forth
.to("#slideContainer", 1, { z: -180, delay: 0.6 })
.to("#slideContainer", 1, { x: "-75%" })
.to("#slideContainer", 1, { z: 0 })
var scene = new ScrollMagic.Scene({
triggerElement: "#pinContainer",
triggerHook: "onLeave",
duration: "600%" //이 값이 클 수록 천천히 덮어씀
})
.setPin("#pinContainer")
.setTween(wipeAnimation)
.addIndicators()
.addTo(controller);
#pinContainer에게 perspective를 주었으니 z값을 이용해 slideContainer에게 3D 입체 효과를 줄 수 있습니다.
마찬가지로 scene의 duration 값이 클 수록 더 많은 스크롤이 필요합니다.
See the Pen ScrollMagic Demo (9) - Dynamic Section Slide by NY KIM (@nykim_) on CodePen.
3. SVG 라인 드로잉
스크롤을 하면 SVG 라인이 그려지는 매직!
을 지금부터 만들어봅시다 XD
우선 SVG 라인 애니메이션에 대해 간단히 짚고 넘어가겠습니다.
이때 SVG는 당연하게도 stroke속성을 갖고 있어야 하는데, 우리는 이 stroke를 움직이게 만들 거니까요!
stroke-dassharray 라는 CSS 속성이 있습니다. 이 속성을 적용시키면, 선이 대쉬 형태가 되며 값만큼 간격을 갖게 됩니다.
예를 들어 path의 길이가 100이고, dasharray 값이 50이라면 path는 절반만 보입니다.
만약 'dasharray 값 = path 길이'라면 path는 온전히 보이게 됩니다. path의 길이만큼 간격을 갖게 되니까요.
한편 이때! stroke-dashoffset 이란 속성을 줘봅니다. 이는 dasharray의 시작 위치를 설정합니다.
그럼 'dasharray 값 = path 길이'일 때, 'dashoffset 값 = path 길이'라면 어떨까요? 그럼 path는 보이지 않게 됩니다 (두둥)
그래서 결국 라인 드로잉 애니메이션을 보여주려면,
'dashoffset 값 = dasharray 값 = path 길이'으로 설정한 다음, dashoffset의 값을 점점 0으로 줄여가면 됩니다.
path의 길이는 getTotalLength() 메서드를 통해 구할 수 있습니다.
그럼 직접 만들어보며 감을 익혀보죠!
우선 아무 SVG나 준비합니다. 당연히 <path d="..."/> 형태여야 합니다!
그리고 path의 길이를 구해 style로 지정하는 함수를 작성합니다.
var st = document.querySelector(".st1");
function pathPrepare(el) {
var lineLength = el.getTotalLength();
el.style.strokeDasharray = lineLength;
el.style.strokeDashoffset = lineLength;
}
pathPrepare(st);
아까 말했듯, strokeDasharray와 strokeDashoffset을 path길이와 동일하게 맞춰주었습니다.
그런 다음 라이브러리를 사용하여,
strokeDashoffset을 0으로 만듭니다.
var controller = new ScrollMagic.Controller();
var tween = new TimelineMax()
.add(TweenMax.to(st, 0.9, {
strokeDashoffset: 0,
ease: Linear.easeNone
}))
.add(TweenMax.to(st, 1, {
stroke: "#ffffff",
ease: Linear.easeNone
}), 0);
var scene = new ScrollMagic.Scene({
triggerElement: "#trigger1",
duration: 200,
tweenChanges: true
})
.setTween(tween)
.addIndicators({
colorStart: "#ffffff",
colorEnd: "#000000"
})
.addTo(controller);
See the Pen ScrollMagic Demo (10) - SVG line animation by NY KIM (@nykim_) on CodePen.
4. 컨테이너 스크롤
body에서 스크롤하는 게 아니라, 커스텀 컨테이너 내부에 스크롤 애니메이션을 작성할 수도 있습니다.
Controller 옵션으로 {container: "컨테이너명"}을 지정하면 됩니다.
var controller = new ScrollMagic.Controller({
container: "#container"
});
//....
See the Pen ScrollMagic Demo (11) - Container by NY KIM (@nykim_) on CodePen.
5. 앵커 링크 스크롤링
앵커 클릭 시 해당 지점으로 스크롤시킬 때는 GSAP의 scrollToPlugin을 이용할 수 있습니다.
플러그인으므로 추가로 가져다 써야합니다.
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.1.3/plugins/ScrollToPlugin.min.js"></script>
그리고 컨트롤러의 scrollTo를 TweenMax로 정의해줍니다.
scrollTo() 메서드에 대한 내용은 공식 문서를 참고하세요.
controller.scrollTo(function (newpos) {
TweenMax.to(window, 0.5, {scrollTo: {y: newpos}});
});
그런 다음 앵커를 눌렀을 때 해당 위치로 이동하게끔 처리합니다.
원한다면 pushState()를 통해 브라우저 히스토리에 추가할 수도 있습니다.
var menu = document.querySelector("#menu");
menu.addEventListener("click", function (e) {
var id = e.target.hash;
e.preventDefault();
controller.scrollTo(id);
if (window.history && window.history.pushState) {
history.pushState("", document.title, id);
}
});
See the Pen ScrollMagic Demo (12) - Anchor by NY KIM (@nykim_) on CodePen.
6. 패럴렉스 스크롤
이번에는 스크롤 애니메이션에서 자주 쓰이는 패럴렉스를 배워봅니다 ;-9
배경화면이 교차되어 입체적으로 보이게 하는 방법인데,
background-position 값을 저마다 다르게 주면 됩니다.
여기 총 네 개의 배경 레이어가 있습니다.
<div id="backContainer">
<div class="back back1"></div>
<div class="back back2"></div>
<div class="back back3"></div>
<div class="back back4"></div>
</div>
그런 다음 absolute 시켜놨죠.
#backContainer {
overflow-x: hidden;
overflow-y: hidden;
width: 100%;
height: 101vh;
}
.back {
position: absolute;
width: 300%;
height: 100%;
background-repeat: repeat-x;
}
마지막으로 타임라인을 생성하고, 백그라운드 포지션 값을 바꿔줍니다.
이때 duration으로 스크롤 길이를 조절하고, setPin으로 화면에 고정시킬 수 있습니다.
(function () {
var controller = new ScrollMagic.Controller();
var tween = new TimelineMax()
.add([
TweenMax.to("#backContainer .back1", 1, {
backgroundPosition: "-200%",
ease: Linear.easeNone
}),
TweenMax.to("#backContainer .back2", 1, {
backgroundPosition: "-150% 0",
ease: Linear.easeNone
}),
TweenMax.to("#backContainer .back3", 1, {
backgroundPosition: "-50% 0",
ease: Linear.easeNone
}),
TweenMax.to("#backContainer .back4", 1, {
backgroundPosition: "-100% 0",
ease: Linear.easeNone
})
]);
var scene1 = new ScrollMagic.Scene({
duration: "1000%"
})
.setTween(tween)
.setPin("#backContainer")
.addIndicators();
controller.addScene(scene1);
}())
(이미지 출처는 요기요!)
7. 패럴렉스 섹션
이번 패럴렉스는 이미지가 아니라 섹션에 적용해보겠습니다.
이 효과를 적용하려면 부모 컨테이너가 필요합니다.
<div id="parallax1" class="parallaxParent">
<div class="background bg1">
<strong class="title">Parallax</strong>
</div>
</div>
그리고 부모 컨테이너의 높이는 뷰포트 전체로 정합니다.
자식 요소의 높이는 200%로 설정하되, top:-100% 값을 줘서 중앙이 보이게 합니다.
.parallaxParent {
height: 100vh;
overflow: hidden;
}
.background {
height: 200%;
position: relative;
top: -100%;
}
대략적인 구조를 그림으로 표현하면 이런 느낌이에요! 👇
이 상태에서 우리가 해줄 건, 스크롤해서 parallaxParent에 닿으면
그 자식인 background가 아래로 이동하게끔 합니다.
그럼 height가 200%여서 가려져있던 background의 윗부분이 보이겠죠?
여기에 duration을 지정해줘서 스크롤에 따라 이동하게 하면, 우리가 원하는 패럴렉스 효과를 줄 수 있습니다.
위 내용을 코드로 바꾸면 이렇게 됩니다.
(function () {
var controller = new ScrollMagic.Controller({
globalSceneOptions: {triggerHook: "onEnter"}
});
new ScrollMagic
.Scene({triggerElement: "#parallax1", duration: "200%"})
.setTween("#parallax1 > div", {y: "40%", ease: Linear.easeNone})
.addIndicators()
.addTo(controller);
new ScrollMagic
.Scene({triggerElement: "#parallax2", duration: "175%"})
.setTween("#parallax2 > div", {y: "30%", ease: Linear.easeNone})
.addIndicators()
.addTo(controller);
}())
See the Pen ScrollMagic Demo (13) - Parallax Sections by NY KIM (@nykim_) on CodePen.
이렇게 중급 편도 무사히 마쳤습니다! 🥰