Parallax показване на поредни елементи

Показване при скрол (част 3 – AOS)

И след като се запознахме с основите на подобни ефекти, нека приложим анимациите с AOS.

Анимации с AOS

AOS е съкращение от „Animate on Scroll“ (анимации при скрол). В общи линии върши това, което написахме custom предния път. Защо тогава да зареждаме допълнително 20KB JS, като имаме едни 20-30 реда, които вършат същата работа? Защото AOS всъщност върши повече.

AOS е библиотека, върху чиято разработка някой се е трудил доста повече от нас. Освен това е тествана от хиляди. За последния месец е бил изтеглен почти 80 000 пъти и то само през npm (вероятно и има хора, които са го изтеглили директно от GitHub).

Освен, че покрива нашата функционалност, е разработена така, че конфигурацията да се прави лесно с data-атрибути направо в HTML-а, поддържа easing функции и работи в обратна посока (при скрол нагоре крие обратно елементите пак с анимация). И това са само най-основните преимущества.

Мигриране към AOS

Нека копираме файловете си от предния път, като премахнем functions.js файла (той няма да ни е нужен), както и animate.css стиловете. AOS идва със свои стилове, но ако по някаква причина държите да ползвате Animate.CSS, AOS го позволява с малко допълнителни настройки.

Да добавим и кода на самия AOS. Аз използвах npm, така че имам и source файлове и dependency-та, но вие можете просто да използвате CDN-а описан най-долу на http://michalsnik.github.io/aos/.

След това нека изтрием всички pending класове, които бяхме добавили към елементи и вместо това им добавим data-aos="fade-up".

Инициализиране на анимации с AOS

За да видим някакви анимации към момента трябва да инициализираме AOS.

За целта просто добавете най-долу на страницата (преди затварящия </body> таг):

<script>
AOS.init();
</script>

Ако презаредите страницата ще видите, че вече сме почти готови. Остават обаче забавянията, които преди имахме към някои поредни елементи.

Забавяне на анимацията при поредни елементи

Изтрийте частта от CSS-а, която имахме за тях:

.feature__item.animated:nth-child(2) { animation-delay: 200ms; }
.feature__item.animated:nth-child(3) { animation-delay: 400ms; }

.media.animated { animation-delay: 200ms; }

.column__item.animated:nth-child(2) { animation-delay: 200ms; }

Към втория и третия .feature__item можем направо в markup-а да добавим съответно data-aos-delay="150" и data-aos-delay="300".

data-aos-delay="150" добавяме и към втория .column__item.

Когато имаме множество поредни елементи

Стигаме обаче пак до нашата галерия с 16 картинки. Както преди не искахме ръчно да добавяме delay към тях, сега това се повтаря с AOS.

В повечето случаи, ако правим нещо подобно вероятно ще използваме PHP код и тогава няма да е трудно да зададем атрибута. Просто ще имаме една променлива, която нараства със 150 всеки път и така ще е приложена на всеки таг. Тук обаче не използваме PHP и ще потърсим друг метод.

Макар и JavaScript да не е сървърен език, ние пак можем да го ползваме за генериране на markup. Можем да използваме document.write() за „писане“ на какъвто и да е код.

Премахнете всички li.gallery__item и на тяхно място отворете един <script> таг.

Първо нека генерираме масив с всички номера на картинки, които ще са ни нужни (от 1 до 16).

Можем да използваме:

const indexes = Array.from(Array(16).keys());

Тъй като имаме вложени и chain-нати функции това може да е малко объркващо. Нека започнем отвътре навън:

Array(16) създава масив с 16 празни елемента.

Когато chain-нем .keys() към резултата, това връща итератор, където елементите са индексите на първия. Те от своя страна са числата от 0 до 15.

Ние искахме от 1 до 16, но лесно можем при принтиране на числото просто да добавяме по 1.

Това, че .keys() не връща точно масив, а итератор за нас означава, че трябва да го преобразуваме. Това правим с Array.from().

Template Literals

Официално са одобрени като синтаксис на JavaScript през 2015, така че все още не всички са напълно свикнали с употребата им.

Това, което представляват е писане на string, вътре в който можем да включим директно променливи, които JS ще замени със стойностите им.

Така, че ако имаме променлива age = 18, то

var sentence = `В България трябва да си на ${age} години, за да може да шофираш`;

ще присвои стойност на променливата sentence, където ${age} е заменено с 18.

Важно е вместо обикновени единични или двойни кавички (', ") да се използват backticks: „`“ (клавишът се намира точно под Esc на клавиатурата).

По принцип можем да постигнем същото и просто с:

var sentence = "В България трябва да си на " + age + "години, за да може да шофираш";

Но постоянното отваряне и затваряне на кавички може да е малко изнервящо. Освен това има други специални ситуации, в които употребата на обикновени кавички и конкатениране може да доведе до изписване на още повече код.

И сега на document.write() ще подадем следния аргумент:

indexes.map(key =>
	`<li class="gallery__item" data-aos="fade-up" data-aos-delay="${(key % 4) * 150}">
		<img width="420" height="420" src="gallery-${(key + 1).toString().padStart(2, '0')}.jpg" alt="cloud" />
	</li>`
).join('')

Тук може да има нужда от малко повече разяснения:

indexes.map означава, че обходим всеки елемент от масива indexes и за обхожданата стойност ще изпълним някакъв код. Този код трябва да върне резултат, който после ще се използва в построяването на нов масив.

Така, че ако имахме const incremented = indexes.map(key => key + 1), тогава incremented щеше да е нов масив със стойности от 1 до 16 (както отначало искахме), защото за всяка стойност от indexes щеше да ѝ бъде добавено 1 и да се състави нов масив с тези стойности.

По-голямата част от самия template literal е HTML кода, който ни трябва, така че него няма да го обясняваме.

За data-aos-delay имаме (key % 4) * 150. Защо делим модулно на 4, вместо директно да умножаваме по 150? Защото преди трябваше всяка картинка да се покаже със закъснение спрямо предната. С AOS обаче картинките не са свързани помежду си, а при scroll на екрана се появяват едновременно 4 картинки. Така за 2ра, 3та и 4та трябва да добавим съответно по 150, 300 и 450 милисекунди закъснение.

Но при скрол още по-надолу, следващия ред не трябва да има по 600, 750 и т.н. милисекунди закъснение, тъй като до 4тия ред ще чакаме по няколко секунди докато се появят снимките.

Pad String

За пътя до самите снимки имаме (key + 1).toString().padStart(2, '0').

Частта + 1 е ясна – правим го, защото имаме масив от 0 до 15 (извинявам се, ако е изнервящо, че вече го повтарям 3ти път).

После се уверяваме, че числото се третира като текст чрез .toString(). Това е нужно, защото следващата функция работи с текст, а не с числа. Тази функция padStart() позволява към текст по-кратък от определен брой символи, в началото да повторим толкова пъти друг символ, така че да достигне търсената дължина.

Или иначе казано – при число с 1 цифра, можем да добавим 0 отпред (защото така сме си наименували картинките).

И най-накрая след всичко това имаме един .join(''). Този .map(), който сме направили ни връща масив с HTML кода за всяка картинка. За да го изпишем на екрана ние долепяме всеки от елементите от масива, използвайки празен string (“) за „лепило“.

Пример

И накрая имаме https://magadanski.com/demo/parallax-aos/.

Вашият коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *

Този сайт използва Akismet за намаляване на спама. Научете как се обработват данните ви за коментари.