
ScrollMagic
ScrollMagic е една от алтернативите на Scrollr. Сама по себе си библиотеката позволява да фиксираме елемент на екрана при scroll. В комбинация с GSAP обаче става мощно средство за постигане на parallax ефекти.
Можете да изтеглите библиотеката от http://scrollmagic.io/. А в този урок ще разгледаме няколко елементарни примера как да я използваме.
HTML
Преди да започнем със самите паралакс ефекти, нека първо създадем една семпла страница. Нека в нея включим едно лого, което ще анимираме:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Parallax ScrollMagic</title>
</head>
<body>
<span id="logo">M</span>
</body>
</html>
CSS
Нека добавим basic reset CSS:
* { margin: 0; padding: 0; }
html, body { width: 100%; height: 360vh; } /* 360vh за да имаме поле за scroll и parallax */
body { background: #E0E0E0; color: #333; font: normal 14px/1.35 Arial, Helvetica, sans-seerif; }
Нека зададем следните стилове на логото, за да прилича и то на нещо:
#logo {
background: #2060DF; /* син фон */
color: #FFF; /* бял текст */
font: normal 192px/1.13 Verdana, Arial, sans-serif; /* голям font-size и font-family, което ни харесва; особения line-height е за да държим текста вертикално центриран според фона */
display: inline-block; /* за да можем да зададем фиксирани елементи на span елемент */
width: 1.2em; /* еднакви широчина и височина, които са базирани на шрифта; така става красиво квадратче */
height: 1.2em;
text-align: center; /* за да излиза текста хоризонтално центриран */
user-select: none; /* за да се държи повече като картинка и да не може буквата вътре да се селектира */
position: absolute; /* да го позиционираме на празния екран */
top: 100vh; /* да е на дъното, за да подтикне хората да scroll-нат и да видят повече */
left: 50vw; /* да е хоризонтално центрирано */
transform: translate(-50%, -50%); /* да компенсира размерите на елемента, вместо горния-ляв ъгъл да е в центъра на екрана */
}
JavaScript
И сега вече идва ред на JavaScript-а.
Нека първо заредим всичко, което ще ни трябва:
- TweenLite.min.js — може и TweenMax.min.js, но нека зареждаме само наистина каквото ни трябва
- CSSPlugin.min.js — това ще ни трябва, за да анимираме стилове
- EasePack.min.js — по принцип можем без това, но някои анимации стават по-естествени когато имаме easing
- ScrollMagic.min.js — все пак пишем урок за него
- animation.gsap.min.js — интеграция между ScrollMagic и TweenLite/TweenMax; без това “лепило” между двете, страницата ще доведе до грешки
<script src="TweenLite.min.js"></script>
<script src="CSSPlugin.min.js"></script>
<script src="EasePack.min.js"></script>
<script src="ScrollMagic.min.js"></script>
<script src="animation.gsap.min.js"></script>
А сега вече идва и реда на нашия програмен код, който ще задвижи елементите:
Controller
const controller = new ScrollMagic.Controller();
Вътрешният начин на работа на ScrollMagic изисква да имаме един контролер, който е пряко свързан към scroll bar-а на страницата.
Възможно е при елементи с вътрешен scroll да ви се наложи да регистрирате 2 контролера, но не се сещам за практическа причина за подобно нещо.
Scene
След това нека добавим възможно най-елементарното нещо, което ScrollMagic може:
const scenePin = new ScrollMagic.Scene({ triggerElement: '#logo' })
.setPin('#logo')
.addTo(controller);
Да започнем с концепцията за сцени. Всяка една сцена в ScrollMagic трябва да бъде асоциирана с контролер, който да я задвижи.
Една сцена е редно да съдържа една промяна по стилове (примерно да направи елемент фиксиран на екрана, или да добави клас, или пък да го обвърже с промяна на други стилови параметри и т.н.).
Първият аргумент, който подаваме на конструктора е обект с настройки на сцената. Тези настройки включват:
triggerElement
— може да бъде string с CSS селектор до елемента, за който трябва анимацията да се отнася или направо DOM елементtriggerHook
— може да е число от 0 до 1. Има и три стойности, които могат да се представят като string:onEnter
или просто 1 (100% разстояние от горния край на екрана) — обозначава, че ScrollMagic ще си свърши работата когато елементът е най-долу на екрана (влиза във viewport-а при scroll)onCenter
или 0.5 (50% от viewport-а) — анимацията ще се изпълни, когато елементът попадне в центъра на екрана. Това е и стойността по подразбиране, която ще се използва, ако не зададете другоonLeave
или 0 — когато елементът е най-горе и след още малко scroll вече ще излезе от viewport-а.
offset
— по подразбиране е 0; иначе може да се използва вместоtriggerHook
или в комбинация с него, за да изместите началото на сцената нагоре или надолу по екрана с фиксирана стойност в пиксели (вместо в проценти, както идва отtriggerHook
)duration
— “продължителност” на анимацията. Или с други думи — при scroll на още колко пиксела надолу трябва сцената да приключиreverse
— дали при scroll в обратна посока сцената също да се изпълни наобратно. По подрадбиране еtrue
loglevel
— свързано е с debug-ване. Ако ви трябват повече детайли най-добре се обърнете към официалната документация на http://scrollmagic.io/docs/ScrollMagic.Scene.html#constructor
setPin
След като вече имаме сцена е редно да обвържем някакво действие с нея. Казахме, че ще започнем с най-елементарното, което е просто да фиксираме елемента на екрана. Позицията му се сменя с fixed
и той повече не мърда. Така де — защото не сме задали duration
. В противен случай щеше да се фиксира само за определено количество scroll, след което пак щеше да си излезе нагоре от екрана, ако продължим да scroll-ваме.
addTo
Накрая с метода addTo
на сцената я добавяме към контролера, който сме регистрирали по-рано.
Интеграция с GSAP
Интересната част идва, когато обвържем ScrollMagic с анимации дефинирани с GSAP.
По принцип можем просто при достигане на triggerElement
-а до triggerHook
-а да изпълним някоя анимация, която сме дефинирали с GSAP. Това обаче не е най-интересното, което можем да направим.
По-забавно би било, ако можем да използваме scroll-а на страницата като инструмент за превъртане на GSAP анимация. Така че като спрем да scroll-ваме, анимацията също да спре. Когато тръгнем да scroll-ваме наобратно — анимацията да се reverse-не. Ако scroll-ваме бавно или бързо — анимацията да се изпълнява със съответна скорост. Това вече може да доведе до parallax.
От квадрат към кръг
Нека след като вече логото е pin-нато в средата на екрана започнем нова сцена:
const vh = window.screen.availHeight / 100;
const sceneCircle = new ScrollMagic.Scene({ triggerElement: '#logo', duration: 50 * vh, offset: 10 * vh })
Константата vh
си я регистрирам като помощник за изчисляване на това колко пиксела съответстват на 1vh
в CSS.
В случая няма да си даваме зор да преизчисляваме при resize на екрана, но ако разработвате нещо в реални условия би било добре да си напишете кода така, че при промяна на размера на прозореца на браузъра, JavaScript-а да не се счупи.
Като продължителност на сцената задаваме 50vh
(50 * vh
), като искаме да я изместим и леко надолу от средата на екрана (10vh
след като вече елементът е pin-нат).
setTween
След това идва ред на setTween
метода на сцената. Точно за тук ни е нужен animation.gsap.min.js
, иначе ще имаме JS грешка и GSAP анимацията няма да се обвърже правилно със scroll-а на страницата.
.setTween(new TweenLite.to('#logo', 1, { className: '+=circle' }))
Като параметър на setTween
подаваме нов TweenLite
(може и TweenMax
).
Последния го обвързваме към #logo
. Задаваме продължителност 1 секунда, която реално няма да има значение, тъй като анимацията ще е обвързана със scroll-а. Накрая като настройки обаче не подаваме конкретни стилове, а указваме на GSAP да добави клас circle
.
Реално не се задава този клас, а посредством CSSPlugin.min.js
, GSAP проверява какви стилове ще има елементът при прилагане на този клас и за продължителността на анимацията пресмята средни стойности на стиловете отпреди назначаване на класа, до крайната стойност.
Нека добавим следния CSS стил:
.circle { border-radius: 50%; }
Накрая нека добавим сцената към контролера, който имаме с addTo(controller)
.
Търкул-търкул
След като логото вече е кръгло, нека добавим и трета сцена, която да го завърти:
const sceneBarrelRoll = new ScrollMagic.Scene({ triggerElement: '#logo', duration: 100 * vh, offset: 75 * vh })
.setTween(new TweenLite.to('#logo', 1, { rotation: 360, ease: Power1.easeInOut }))
.addTo(controller);
triggerElement
-ът отново е #logo
. Продължителността е scroll на един цял екран. offset
-ът е изчислен на базата на предходните анимации, така че да се изпълни след като логото вече е станало на кръг.
Чрез setTween
задаваме завъртане на 360 градуса, на което задаваме easeInOut
от първа степен. Ако минем без този easing можем и да не зареждаме EasePack.min.js
, описан по-горе.
Пример
Резултатът от нашите анимации можете да видите на https://magadanski.com/demo/parallax-scrollmagic/.