Створення анімації на базі JavaScript за допомогою бібліотеки Anime.js. Частина 3 [*]


У цій статті мова піде про те, як навчитися встановлювати значення властивостей, використовуючи звичайні числа, значення на основі функцій і ключові кадри. Також ви навчитеся регулювати відтворення і послідовність анімацій.

У попередній статті можна було ознайомитися з різними видами параметрів, які служать для управління цільовими елементами. Також в ній пояснюється, як правильно використати такі параметри, як duration і delay, які відповідають за тривалість і затримку анімації.

Визначення значень властивостей

Anime.js дозволяє визначати кінцеві значення властивостей цільових елементів, що анімуються. Початкове значення анімації – значення властивостей за умовчанням. Будь-яка властивість, яка визначається за допомогою CSS-коду, може виступати початковим значенням. Існує декілька способів визначення кінцевого значення :

  • Їм може бути безрозмірна величина. У такому разі використовуються величини властивостей за умовчанням для обчислення яких-небудь значень властивостей.
  • Значення можуть визначатися у вигляді рядка, проте у такому разі він повинен містити принаймні одно числове значення. Приклади значень рядка: 10vh, 80% чи 9.125turn.

Замість абсолютного значення можна визначити значення властивості відносно його поточного значення. Наприклад, можна встановити для translateY кінцеве значення на 150 px більше, ніж воно є, використовуючи +=150px. Пам’ятайте, що можна використати додавання, множення або віднімання тільки під час визначення відносних значень.

Для анімації кольорів не можна використати такі значення, як red, black чи blue. При таких установках анімація не спрацює взагалі. Єдиний правильний спосіб позначення кольорів при анімації – шістнадцятиричний код, RGB і HSL.

Як ви могли помітити, початкове значення для анімації цільових елементів не було вказане. Anime.js автоматично визначає початкове значення на основі CSS і значення за умовчанням цих властивостей. Проте ви можете вказати початкове значення, відмінне від значення за умовчанням. Перший елемент в масиві означає початкове значення, а другий – кінцеве.

Замість використання того ж самого кінцевого значення для усіх цільових елементів можна використати функції для установки різних значень для різних параметрів. Це схоже на визначення властивостей на основі функції.

var uniqueTranslation = anime ({ targets: '.square', translateY: function (el, i) { return 50 *  (i + 1); }, autoplay: false}); var randomScaling = anime ({ targets: '.square', scale: function (el, i){ return Math.random () * 1.5 + i / 10; },
autoplay: false}); var randomRotation = anime ({ targets: '.square', rotate: function (){ return anime.random (- 180, 180); }, autoplay: false}); var randomRadius = anime ({ targets: '.square', borderRadius: function (el) { return 20 + Math.random () * el.offsetWidth / 4; }, autoplay: false}); var randomAll = anime ({ targets: '.square', translateY: function (el, i) { return 50 + 50 * i; }, scale: function (el, i) { return Math.random () * 1.5 + i / 10; }, rotate: function (){ return anime.random (- 180, 180); }, borderRadius: function (el) { return Math.random () * el.offsetWidth / 2; }, duration: function (){ return anime.random (1500, 2400); }, delay: function (){ return anime.random (0, 1000); }, autoplay: false});

Для установки значення властивості translateY у функції uniqueTranslation використовується індекс елементу. Використання 50 * (i + 1) збільшує значення translateY кожного елементу на 50 пікселів.

Анімація масштабування (функція randomScaling у прикладі вище) також залежить від індексу елементу, але додатково рандомізується вбудованою функцією Math.random (). Вона генерує псевдовипадкове число з плаваючою точкою зі значенням менше одиниці. У такому разі елементи масштабуватимуться випадковим чином, але частина коду i/10 трохи збільшує вірогідність появи елементів, які кінець кінцем матимуть більший розмір.

Для анімації обертання (функція randomRotation у прикладі вище) використовується допоміжна функція anime.random (a, b), що формує випадкові числа в діапазоні від – 180 до 180. Функція корисна для привласнення випадкових цілих чисел властивостям ніби translateY і rotate. Використання цієї функції для анімації масштабування приведе до формування надмірно великих або малих масштабів.

Значення міри округлення кутів для різних елементів визначається шляхом обчислення ширини цільових елементів за допомогою параметра el усередині функції. Останні рядки коду вище задають випадкові значення параметрам duration і delay.

Як бачите, анімація, приведена в прикладі вище, носить випадковий характер. Відповідно, взаємозв’язок між значеннями властивостей різних елементів просто відсутній. У реальному житті розумніше використати значення, які нададуть вашій анімації сенс.

Можна анімувати різні властивості цільових об’єктів за допомогою ключових кадрів. Кожен ключовий кадр складається з об’єкту масиву властивостей. Можна використати цей об’єкт для визначення значення властивостей, а також для duration, delay і easing. Код нижче створює анімацію переходу на основі ключових кадрів:

var keyframeTranslation = anime ({ targets: '.square', translateY: [ { value: 100, duration: 500}, { value: 300, duration: 1000, delay: 1000}, { value: 40, duration: 500, delay: 1000} ], autoplay: false});
var keyframeAll = anime ({ targets: '.square', translateY: [ { value: 100, duration: 500}, { value: 300, duration: 1000, delay: 1000}, { value: 40, duration: 500, delay: 1000} ], scale: [ { value: 1.1, duration: 500}, { value: 0.5, duration: 1000, delay: 1000}, { value: 1, duration: 500, delay: 1000} ], rotate: [ { value: 60, duration: 500}, { value: - 60, duration: 1000, delay: 1000}, { value: 75, duration: 500, delay: 1000} ], borderRadius: [ { value: 10, duration: 500}, { value: 50, duration: 1000, delay: 1000}, { value: 25, duration: 500, delay: 1000} ], delay: function (el, i) { return 100 *  (i + 1) }, autoplay: false});

Ви можете анімувати декілька властивостей відразу, вказуючи різні або однакові значення для усіх параметрів. У другому випадку глобальний параметр delay застосовує початкову затримку для усіх елементів, виходячи з індексу кожного елементу. Ця затримка незалежна від тих, які застосовуються до кожної властивості усередині ключових кадрів.

Створення і управління тимчасовою шкалою анімації

Зберегти правильне значення затримки при збільшенні складності анімаційної послідовності досить важко. Будь-яка зміна в тривалості однієї анімації змусить вас перерахувати усі значення затримки, щоб зберегти початкову послідовність.

Щоб розв’язати цю проблему, краще всього використати тимчасову шкалу для контролю послідовності анімації. Для її створення використовується функція anime.timeline (). Також можна передати різні параметри в цю функцію у вигляді об’єктів. Ці параметри можуть встановлювати напрям, в якому тимчасова шкала відтворюється, кількість циклів, а також параметр autoplay, щоб визначити, чи повинна анімація відтворюватися автоматично. З цими параметрами ви можете детальніше ознайомитися в попередній частині.

На тимчасову шкалу можна додавати різні анімації за допомогою методу add (). Усі анімації, додані на тимчасову шкалу, будуть відтворені в тому порядку, в якому вони були додані. Можна вказувати абсолютні або відносні значення зміщення для управління порядком відтворення анімацій.

Коли використовуються відносні значення зміщення, початковий час поточної анімації визначається відносно часу закінчення попередньою.

Відносне зміщення буває трьох типів:

+=n – анімація відтворюється через N мілісекунд після закінчення попередньою.
-=n – анімація відтворюється за N мілісекунд до закінчення попередньою.
*=n – анімація відтворюється через ту кількість мілісекунд, яка рівна n-кратної тривалості попередньої анімації. Приклад: ви встановили зміщення, рівне 2 ( offset: '*=2'), попередня анімація триває 500 мілісекунд. Множимо 2 на 500 і отримуємо 1000 – через цей проміжок часу запуститься наступна анімація.

Код нижче демонструє, як можна додати звичайну тимчасову шкалу і тимчасову шкалу з відносним зміщенням:

var basicTimeline = anime.timeline ({ direction: " alternate", loop: 2, autoplay: false}); basicTimeline.add ({ targets: '.square', translateY: 200 }).add ({ targets: '.red', translateY: 100 }).add ({ targets: '.blue', translateY: 0 }); var offsetTimeline = anime.timeline ({ direction: " alternate", loop: 2, autoplay: false}); offsetTimeline.add ({ targets: '.square', translateY: 200 }).add ({ targets: '.red', offset: '+=1000', translateY: 100 }).add ({ targets: '.blue', offset: '*=2', translateY: 0 });

У прикладі анімації вище натисніть на кнопку Offset Timeline. Ви побачите затримку в 2 секунди між кінцем анімації червоних квадратів і початком анімації синіх.

Параметр duration не був визначений для червоних квадратів, тому використовується значення за умовчанням, рівне 1000 мілісекундам або одній секунді. Зміщення з множенням (*=n) для блакитних квадратів збільшує це значення в два рази, внаслідок чого і з’являється затримка анімації в дві секунди.

При використанні абсолютного значення зміщення початковий час анімації настроюється відносно початку тимчасової шкали. Можна змінити послідовність відтворення анімації, використовуючи великі значення зміщення, які реалізуються на початку тимчасової шкали.

Налаштування відтворення

Функція play() дозволяє запустити анімацію або з початкової позиції, або з моменту, на якому вона була зупинена. Pause() зупиняє анімацію на час виклику, restart() запускає анімацію з початку, незалежно від поточного стану. Функція seek(n) використовується для перемотування анімації, де n – число в мілісекундах.

Якщо анімація завершилася, її не можна запустити знову за допомогою функції play(). Для повторного відтворення анімації використовується тільки функція restart().

var slowAnimation = anime ({ targets: '.square', translateY: 250, borderRadius: 50, duration: 4000, easing: 'linear', autoplay: false}); document.querySelector ('.play').onclick = slowAnimation.play;
document.querySelector ('.pause').onclick = slowAnimation.pause;document.querySelector ('.restart').onclick = slowAnimation.restart; var seekInput = document.querySelector ('.seek'); seekInput.oninput = function (){ slowAnimation.seek (slowAnimation.duration *  (seekInput.value / 100));};

Зверніть увагу, що для перемотування анімації використовується не просто seekInput.value. Так було зроблено через те, що в розмітці зумовлено максимальне значення для перемотування, рівне 100 мілісекундам. Безпосереднє використання seekInput.value дозволяє здійснювати перемотування тільки до 100-ої мілісекунди. Шляхом множення вхідного діапазону і тривалості анімації можна шукати потрібний момент на повзунку від початку до кінця.

Висновок

У наступній статті ви познайомитеся із зворотними викликами, які можна використати для виконання функцій залежно від прогресу анімації. Також в наступну статтю включений розділ з анімаціями, пов’язаними з векторним форматом SVG.

Переклад статті “JavaScript – Based Animations Using Anime.js, Part 3: Values, Timeline, and Playback”

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *