Уявіть собі це: ви приєднуєтеся до нового проекту, занурюєтеся в кодову базу й протягом перших кількох годин відкриваєте щось надзвичайно знайоме. У таблицях стилів ви знайдете кілька визначень @keyframes для однакових базових анімацій. Три різні ефекти поступового наближення, два-три варіанти слайдів, декілька анімацій масштабування та принаймні дві різні анімації обертання, бо чому б і ні? @keyframes pulse { від { масштаб: 1; } до { масштаб: 1,1; } }
@keyframes bigger-pulse { 0%, 20%, 100% { масштаб: 1; } 10%, 40% { масштаб: 1,2; } }
Якщо цей сценарій здається знайомим, ви не самотні. З мого досвіду в різних проектах одна з найбільш послідовних швидких перемог, яку я можу досягти, це консолідація та стандартизація ключових кадрів. Це стало настільки надійним шаблоном, що тепер я з нетерпінням чекаю цього очищення як одного з моїх перших завдань на будь-якій новій кодовій базі. Логіка хаосу Ця надмірність має сенс, якщо подумати про це. У повсякденній роботі ми всі використовуємо однакові фундаментальні анімації: згасання, слайди, масштабування, обертання та інші загальні ефекти. Ці анімації досить прості, і легко створити швидке визначення @keyframes, щоб виконати роботу. Без централізованої системи анімації розробники, природно, пишуть ці ключові кадри з нуля, не підозрюючи, що подібні анімації вже існують деінде в кодовій базі. Це особливо часто трапляється під час роботи в архітектурі на основі компонентів (що сьогодні робить більшість із нас), оскільки команди часто працюють паралельно в різних частинах програми. Результат? Анімаційний хаос. Маленька проблема Найочевиднішими проблемами з дублюванням ключових кадрів є втрачений час на розробку та непотрібне розвантаження коду. Кілька визначень ключових кадрів означають кілька місць для оновлення, коли вимоги змінюються. Потрібно налаштувати час анімації, що зникає? Вам потрібно буде вистежити кожен екземпляр у вашій кодовій базі. Хочете стандартизувати функції спрощення? Успіхів у пошуку всіх варіацій. Таке збільшення точок обслуговування робить навіть просте оновлення анімації трудомістким завданням. Більша проблема Це дублювання ключових кадрів створює набагато більш підступну проблему, що ховається під поверхнею: глобальну пастку масштабу. Навіть під час роботи з компонентною архітектурою ключові кадри CSS завжди визначаються в глобальній області. Це означає, що всі ключові кадри застосовуються до всіх компонентів. Завжди. Так, ваша анімація не обов’язково використовує ключові кадри, які ви визначили у своєму компоненті. Він використовує останні ключові кадри, які відповідають тій самій назві, завантаженій у глобальну область. Поки всі ваші ключові кадри ідентичні, це може здаватися незначною проблемою. Але в той момент, коли ви захочете налаштувати анімацію для конкретного випадку використання, у вас виникнуть проблеми або, що ще гірше, ви спричините їх. Або ваша анімація не працюватиме, оскільки інший компонент завантажується після вашого, перезаписуючи ваші ключові кадри, або ваш компонент завантажується останнім і випадково змінює поведінку анімації для кожного іншого компонента, використовуючи назву цього ключового кадру, і ви можете навіть не усвідомлювати цього. Ось простий приклад, який демонструє проблему: .component-one { /* стилі компонентів */ анімація: пульс 1s легкість вхід-вихід нескінченна чергування; }
/* це визначення @keyframes не працюватиме */ @keyframes pulse { від { масштаб: 1; } до { масштаб: 1,1; } }
/* далі в коді... */
.component-two { /* стилі компонентів */ анімація: пульс 1s легкість вхід-вихід нескінченна; }
/* ці ключові кадри застосовуватимуться до обох компонентів */ @keyframes pulse { 0%, 20%, 100% { масштаб: 1; } 10%, 40% { масштаб: 1,2; } }
Обидва компоненти використовують однакову назву анімації, але друге визначення @keyframes перезаписує перше. Тепер і компонент перший, і компонент два використовуватимуть другі ключові кадри, незалежно від того, який компонент визначив які ключові кадри. Перегляньте маркери ключових кадрів Pen - Демо 1 [розгалужено] від Аміта Шина. Найгірша частина? Це часто ідеально працює в локальній розробці, але таємничим чином порушується у виробництві, коли процеси збирання змінюють порядок завантаження ваших таблиць стилів. Ви отримуєте анімацію, яка поводиться по-різному залежно від того, які компоненти завантажуються та в якій послідовності. Рішення: уніфіковані ключові кадри Відповідь на цей хаос напрочуд проста: попередньо визначені динамічні ключові кадри, що зберігаються в спільній таблиці стилів. Замість того, щоб дозволяти кожному компоненту визначати власну анімацію, ми створюємо централізовані ключові кадри, які добре задокументовані та прості длявикористовувати, підтримувати та адаптувати до конкретних потреб вашого проекту. Подумайте про це як про маркери ключових кадрів. Подібно до того, як ми використовуємо маркери для кольорів і інтервалів, і багато хто з нас уже використовує маркери для властивостей анімації, таких як тривалість і функції ослаблення, чому б не використати маркери також для ключових кадрів? Цей підхід можна природним чином інтегрувати з будь-яким поточним робочим процесом маркерів дизайну, який ви використовуєте, водночас вирішуючи як невелику проблему (дублювання коду), так і більшу проблему (конфлікти глобального обсягу) за один раз. Ідея проста: створити єдине джерело правди для всіх наших спільних анімацій. Ця спільна таблиця стилів містить ретельно розроблені ключові кадри, які покривають шаблони анімації, які насправді використовує наш проект. Більше не треба здогадуватися, чи вже десь у нашій кодовій базі існує анімація затухання. Більше немає випадкового перезапису анімацій з інших компонентів. Але ось ключ: це не просто статичні скопійовані та вставлені анімації. Вони розроблені таким чином, щоб бути динамічними та настроюватися за допомогою користувальницьких властивостей CSS, що дозволяє нам підтримувати узгодженість і водночас мати можливість адаптувати анімації до конкретних випадків використання, наприклад, якщо вам потрібна трохи більша «пульсна» анімація в одному місці. Створення першого маркера ключових кадрів Одним із перших низьких результатів, з якими ми повинні зайнятися, є «плавна» анімація. В одному з моїх нещодавніх проектів я знайшов понад дюжину окремих визначень поступового переходу, і так, усі вони просто анімували непрозорість від 0 до 1. Отже, давайте створимо нову таблицю стилів, назвемо її kf-tokens.css, імпортуємо її в наш проект і розмістимо ключові кадри з відповідними коментарями всередині неї. /* keyframes-tokens.css */
/* * Fade In - згасання анімації входу * Використання: анімація: kf-fade-in 0,3s ease-out; */ @keyframes kf-fade-in { від { непрозорість: 0; } до { непрозорість: 1; } }
Ця єдина декларація @keyframes замінює всі ці розрізнені анімації, що зникають, у нашій кодовій базі. Чистий, простий і універсальний. І тепер, коли ми визначили цей маркер, ми можемо використовувати його з будь-якого компонента в нашому проекті: .modal { анімація: kf-fade-in 0,3s ease-out; }
.tooltip { анімація: kf-fade-in 0,2s ease-in-out; }
.notification { анімація: kf-fade-in 0,5s ease-out; }
Дивіться маркери ключових кадрів пера - демо 2 [форк] від Аміта Шина. Примітка. Ми використовуємо префікс kf- в усіх назвах @keyframes. Цей префікс служить простором імен, який запобігає конфліктам іменування з існуючими анімаціями в проекті та відразу дає зрозуміти, що ці ключові кадри походять із нашого файлу маркерів ключових кадрів. Створення динамічного слайда Ключові кадри kf-fade-in чудово працюють, тому що вони прості та мало місця, щоб щось зіпсувати. Однак в інших анімаціях нам потрібно бути набагато динамічнішими, і тут ми можемо використати величезну силу спеціальних властивостей CSS. Ось де маркери ключових кадрів справді сяють порівняно з розрізненими статичними анімаціями. Давайте візьмемо загальний сценарій: «ковзаюча» анімація. Але звідки влізти? 100 пікселів справа? 50% зліва? Чи має він входити з верхньої частини екрана? А може, спливе з дна? Так багато можливостей, але замість того, щоб створювати окремі ключові кадри для кожного напрямку та кожної варіації, ми можемо створити один гнучкий маркер, який адаптується до всіх сценаріїв: /* * Slide In - спрямована анімація слайдів * Використовуйте --kf-slide-from для керування напрямком * За замовчуванням: ковзає зліва (-100%) * Використання: * анімація: kf-slide-in 0.3s ease-out; * --kf-slide-from: -100px 0; // слайд зліва * --kf-slide-from: 100px 0; // слайд праворуч * --kf-slide-from: 0 -50 пікселів; // ковзати зверху */
@keyframes kf-slide-in { від { переклад: var(--kf-slide-from, -100% 0); } до { переклад: 0 0; } }
Тепер ми можемо використовувати цей єдиний маркер @keyframes для будь-якого напрямку слайда, просто змінивши спеціальну властивість --kf-slide-from: .sidebar { анімація: kf-slide-in 0,3s ease-out; /* Використовує значення за замовчуванням: слайди зліва */ }
.notification { анімація: kf-slide-in 0,4s ease-out; --kf-slide-from: 0 -50 пікселів; /* слайд зверху */ }
.modal { анімація: kf-fade-in 0,5 с, kf-slide-in 0,5s cubic-bezier (0,34, 1,56, 0,64, 1); --kf-slide-from: 50px 50px; /* слайд з нижнього правого кута */ }
Такий підхід дає нам неймовірну гнучкість, зберігаючи послідовність. Оголошення одного ключового кадру, нескінченні можливості. Дивіться маркери ключових кадрів Pen - демо 3 [forked] від Аміта Шина. І якщо ми хочемо зробити нашу анімацію ще більш гнучкою, дозволяючи також «висувні» ефекти, ми можемопросто додайте спеціальну властивість --kf-slide-to, подібну до того, що ми побачимо в наступному розділі. Ключові кадри двонаправленого масштабування Ще одна поширена анімація, яка дублюється в проектах, — це ефекти масштабування. Незалежно від того, чи це тонке збільшення для повідомлень, що нагадують, різке збільшення для модалів або ефект м’якого зменшення масштабу для заголовків, анімація масштабування є скрізь. Замість створення окремих ключових кадрів для кожного значення масштабу, давайте створимо один гнучкий набір ключових кадрів kf-zoom:
/* * Zoom - масштаб анімації * Використовуйте --kf-zoom-from і --kf-zoom-to для керування значеннями масштабу * За замовчуванням: масштабування від 80% до 100% (від 0,8 до 1) * Використання: * анімація: kf-zoom 0.2s ease-out; * --kf-zoom-from: 0,5; --kf-zoom-to: 1; // масштабування від 50% до 100% * --kf-zoom-from: 1; --kf-zoom-to: 0; // масштабування від 100% до 0% * --kf-zoom-from: 1; --kf-zoom-to: 1.1; // масштабування від 100% до 110% */
@keyframes kf-zoom { від { масштаб: var(--kf-zoom-from, 0,8); } до { масштаб: var(--kf-zoom-to, 1); } }
За допомогою одного визначення ми можемо отримати будь-який необхідний варіант масштабування: .toast { анімація: kf-slide-in 0,2 с, kf-zoom 0.4s ease-out; --kf-slide-from: 0 100%; /* слайд зверху */ /* Використовується стандартне масштабування: масштабується від 80% до 100% */ }
.modal { анімація: kf-zoom 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); --kf-zoom-from: 0; /* різке збільшення від 0% до 100% */ }
.heading { анімація: kf-fade-in 2s, kf-zoom 2s ease-in; --kf-zoom-від: 1.2; --kf-zoom-to: 0,8; /* плавне зменшення масштабу */ }
Значення за замовчуванням 0,8 (80%) ідеально підходить для більшості елементів інтерфейсу користувача, таких як тост-повідомлення та картки, але його все ще легко налаштувати для особливих випадків. Перегляньте маркери ключових кадрів Pen - Demo 4 [forked] від Аміта Шина. Можливо, ви помітили щось цікаве в останніх прикладах: ми комбінували анімацію. Однією з ключових переваг роботи з токенами @keyframes є те, що вони створені для бездоганної інтеграції один з одним. Ця гладка композиція навмисна, а не випадкова. Пізніше ми обговоримо композицію анімації більш детально, включно з тим, де вони можуть стати проблематичними, але більшість комбінацій є простими та легкими для реалізації. Примітка: під час написання цієї статті, і, можливо, через її написання, я переосмислив всю ідею анімації входу. З усіма останніми досягненнями в CSS, чи потрібні вони нам взагалі? На щастя, Адам Аргайл дослідив ті самі запитання та блискуче висловив їх у своєму блозі. Це не суперечить тому, що тут написано, але це підхід, який варто розглянути, особливо якщо ваші проекти значною мірою залежать від анімації входу. Безперервні анімації Тоді як початкові анімації, як-от «затухання», «ковзання» та «масштабування», відбуваються один раз, а потім припиняються, безперервні анімації повторюються нескінченно, щоб привернути увагу або вказати на поточну активність. Дві найпоширеніші безперервні анімації, які я зустрічаю, це «обертання» (для індикаторів завантаження) і «пульс» (для виділення важливих елементів). Ці анімації представляють унікальні проблеми, коли справа доходить до створення маркерів ключових кадрів. На відміну від вхідних анімацій, які зазвичай переходять з одного стану в інший, безперервні анімації мають бути добре настроюваними у своїх моделях поведінки. Спін-доктор У кожному проекті, здається, використовується кілька обертових анімацій. Одні обертаються за годинниковою стрілкою, інші – проти. Деякі роблять один поворот на 360 градусів, інші роблять кілька обертів для швидшого ефекту. Замість того, щоб створювати окремі ключові кадри для кожної варіації, давайте створимо один гнучкий спін, який обробляє всі сценарії:
/* * Обертання - анімація обертання * Використовуйте --kf-spin-from і --kf-spin-to для керування діапазоном обертання * Використовуйте --kf-spin-turns, щоб контролювати кількість обертів * За замовчуванням: обертається від 0 до 360 градусів (1 повний оберт) * Використання: * анімація: kf-spin 1s linear infinite; * --kf-spin-turns: 2; // 2 повних оберти * --kf-spin-from: 0deg; --kf-spin-to: 180deg; // половина оберту * --kf-spin-from: 0deg; --kf-spin-to: -360deg; // проти годинникової стрілки */
@keyframes kf-spin { від { обертання: var(--kf-spin-from, 0deg); } до { обертати: calc(var(--kf-spin-from, 0deg) + var(--kf-spin-to, 360deg) * var(--kf-spin-turns, 1)); } }
Тепер ми можемо створити будь-який варіант обертання, який нам подобається:
.loading-spinner { анімація: kf-spin 1s linear infinite; /* Використовується за замовчуванням: обертається від 0 градусів до 360 градусів */ }
.fast-loader { анімація: kf-spin 1.2s легкість вхід-вихід нескінченна альтернатива; --kf-обертання: 3; /* 3 повних оберти для кожного напрямку за цикл*/ }
.steped-reverse { анімація: kf-spin 1,5 с кроки (8) нескінченність; --kf-spin-to: -360deg; /* проти годинникової стрілки */ }
.subtle-wiggle { анімація: kf-spin 2s ease-in-out нескінченна альтернатива; --kf-spin-від: -16deg; --kf-spin-to: 32deg; /* хитання на 36 градусів: між -18 градусів і +18 градусів */ }
Дивіться маркери ключових кадрів пера - демо 5 [форк] від Аміта Шина. Принадність цього підходу полягає в тому, що ті самі ключові кадри працюють для завантаження спінерів, піктограм, що обертаються, ефектів ворушіння та навіть складної багатооборотної анімації. Парадокс пульсу Імпульсні анімації складніші, оскільки вони можуть «імпульсувати» різні властивості. Деякі пульсують масштаб, інші пульсують непрозорість, а деякі пульсують такі властивості кольору, як яскравість або насиченість. Замість того, щоб створювати окремі ключові кадри для кожної властивості, ми можемо створити ключові кадри, які працюватимуть з будь-якою властивістю CSS. Ось приклад імпульсного ключового кадру з параметрами масштабу та непрозорості:
/* * Pulse - пульсуюча анімація * Використовуйте --kf-pulse-scale-from і --kf-pulse-scale-to для керування діапазоном шкали * Використовуйте --kf-pulse-opacity-from і --kf-pulse-opacity-to для керування діапазоном непрозорості * За замовчуванням: немає пульсу (усі значення 1) * Використання: * анімація: kf-pulse 2s ease-in-out infinite alternate; * --kf-pulse-scale-from: 0,95; --kf-pulse-scale-to: 1,05; // шкала пульсу * --kf-pulse-opacity-from: 0,7; --kf-pulse-opacity-to: 1; // пульс непрозорості */
@keyframes kf-pulse { від { шкала: var(--kf-pulse-scale-from, 1); непрозорість: var(--kf-pulse-opacity-from, 1); } до { масштаб: var(--kf-pulse-scale-to, 1); непрозорість: var(--kf-pulse-opacity-to, 1); } }
Це створює гнучкий імпульс, який може анімувати кілька властивостей: .call-to-action { анімація: kf-імпульс 0,6 с нескінченно чергується; --kf-pulse-opacity-from: 0,5; /* імпульс непрозорості */ }
.notification-dot { анімація: kf-імпульс 0,6 с легкість вхід-вихід нескінченна чергування; --kf-pulse-scale-from: 0,9; --kf-pulse-scale-to: 1,1; /* шкала пульсу */ }
.text-highlight { анімація: kf-pulse 1,5s нескінченне вивільнення; --kf-pulse-scale-from: 0,8; --kf-pulse-opacity-from: 0,2; /* масштаб і імпульс непрозорості */ }
Дивіться маркери ключових кадрів Pen - демо 6 [forked] від Аміта Шина. Цей єдиний ключовий кадр kf-pulse може впоратися з будь-яким процесом, починаючи від тонкого привернення уваги до драматичних яскравих моментів, і його легко налаштувати. Advanced Easing Однією з чудових переваг використання токенів ключових кадрів є те, як легко можна розширити нашу бібліотеку анімації та забезпечити ефекти, які більшість розробників не потрудилися б створити з нуля, як-от еластичність або відскок. Ось приклад простого маркера ключових кадрів «відскоку», який використовує спеціальну властивість --kf-bounce-from для керування висотою стрибка. /* * Bounce - підстрибуюча анімація входу * Використовуйте --kf-bounce-from для керування висотою стрибка * За замовчуванням: скачки від 100vh (поза екраном) * Використання: * анімація: kf-bounce 3s ease-in; * --kf-bounce-from: 200 пікселів; // стрибок з висоти 200px */
@keyframes kf-bounce { 0% { переклад: 0 calc(var(--kf-bounce-from, 100vh) * -1); }
34% { переклад: 0 calc(var(--kf-bounce-from, 100vh) * -0,4); }
55% { переклад: 0 calc(var(--kf-bounce-from, 100vh) * -0,2); }
72% { переклад: 0 calc(var(--kf-bounce-from, 100vh) * -0,1); }
85% { переклад: 0 calc(var(--kf-bounce-from, 100vh) * -0,05); }
94% { переклад: 0 calc(var(--kf-bounce-from, 100vh) * -0,025); }
99% { переклад: 0 calc(var(--kf-bounce-from, 100vh) * -0,0125); }
22%, 45%, 64%, 79%, 90%, 97%, 100% { переклад: 0 0; функція синхронізації анімації: вивільнення; } }
Такі анімації, як «пружні», дещо складніші через обчислення всередині ключових кадрів. Нам потрібно окремо визначити --kf-elastic-from-X і --kf-elastic-from-Y (обидва необов’язкові), і разом вони дозволять нам створити еластичний вхід з будь-якої точки на екрані.
/* * Elastic In - еластична анімація входу * Використовуйте --kf-elastic-from-X і --kf-elastic-from-Y для керування початковою позицією * За замовчуванням: введення з верхнього центру (0, -100vh) * Використання: * анімація: kf-elastic-in 2s ease-in-out both; * --kf-elastic-from-X: -50px; * --kf-elastic-from-Y: -200px; // ввести з (-50px, -200px) */
@keyframes kf-elastic-in { 0% { переклад: calc(var(--kf-elastic-from-X, -50vw) * 1) calc(var(--kf-elastic-from-Y, 0px) * 1); }
16% { переклад: calc(var(--kf-elastic-from-X, -50vw) * -0,3227) calc(var(--kf-elastic-from-Y, 0px) * -0,3227); }
28% { переклад: calc(var(--kf-elastic-from-X, -50vw) * 0,1312)calc(var(--kf-elastic-from-Y, 0px) * 0,1312); }
44% { переклад: calc(var(--kf-elastic-from-X, -50vw) * -0,0463) calc(var(--kf-elastic-from-Y, 0px) * -0,0463); }
59% { переклад: calc(var(--kf-elastic-from-X, -50vw) * 0,0164) calc(var(--kf-elastic-from-Y, 0px) * 0,0164); }
73% { переклад: calc(var(--kf-elastic-from-X, -50vw) * -0,0058) calc(var(--kf-elastic-from-Y, 0px) * -0,0058); }
88% { переклад: calc(var(--kf-elastic-from-X, -50vw) * 0,0020) calc(var(--kf-elastic-from-Y, 0px) * 0,0020); }
100% { переклад: 0 0; } }
Цей підхід дозволяє легко повторно використовувати та налаштовувати розширені ключові кадри в нашому проекті, просто змінивши одну настроювану властивість.
.bounce-and-zoom { анімація: kf-bounce 3s ease-in, kf-zoom 3s лінійний; --kf-zoom-from: 0; }
.bounce-and-slide { анімація-композиція: доп.; /* Обидві анімації використовують переклад */ анімація: kf-bounce 3s ease-in, kf-slide-in 3s ease-out; --kf-slide-from: -200px; }
.elastic-in { анімація: kf-elastic-in 2s ease-in-out both; }
Перегляньте маркери ключових кадрів Pen - Demo 7 [forked] від Amit Sheen. До цього моменту ми бачили, як ми можемо об’єднати ключові кадри розумним і ефективним способом. Звичайно, ви можете налаштувати речі, щоб вони краще відповідали потребам вашого проекту, але ми розглянули приклади кількох типових анімацій і випадки щоденного використання. І з цими маркерами ключових кадрів ми тепер маємо потужні будівельні блоки для створення узгоджених, підтримуваних анімацій у всьому проекті. Більше ніяких дубльованих ключових кадрів, жодних глобальних конфліктів обсягу. Просто простий і зручний спосіб задовольнити всі наші потреби в анімації. Але справжнє питання полягає в тому, як ми скомпонуємо ці будівельні блоки разом? Збираємо все разом Ми побачили, що об’єднати базові маркери ключових кадрів просто. Нам не потрібно нічого особливого, крім того, щоб визначити першу анімацію, визначити другу, встановити необхідні змінні, і все. /* Збільшення + ковзання */ .toast { анімація: kf-fade-in 0,4 с, kf-slide-in 0,4s кубічний-Безьє (0,34, 1,56, 0,64, 1); --kf-slide-from: 0 40 пікселів; }
/* Збільшення + згасання */ .modal { анімація: kf-fade-in 0,3 с, kf-zoom 0,3 с, кубічний Безьє (0,34, 1,56, 0,64, 1); --kf-zoom-від: 0,7; --kf-zoom-to: 1; }
/* Просунути + імпульс */ .notification { анімація: kf-slide-in 0,5 с, kf-імпульс 1,2 с легкість вхід-вихід нескінченна чергування; --kf-slide-from: -100px 0; --kf-pulse-scale-from: 0,95; --kf-pulse-scale-to: 1,05; }
Ці комбінації працюють чудово, оскільки кожна анімація націлена на різні властивості: непрозорість, трансформацію (переклад/масштаб) тощо. Але іноді виникають конфлікти, і нам потрібно знати, чому та як з ними боротися. Коли дві анімації намагаються анімувати ту саму властивість — наприклад, обидві анімують масштаб або обидві анімують непрозорість — результат буде не таким, як ви очікуєте. За замовчуванням лише одна з анімацій фактично застосовується до цієї властивості, яка є останньою в списку анімацій. Це обмеження того, як CSS обробляє кілька анімацій в одній властивості. Наприклад, це не працюватиме належним чином, оскільки застосовуватиметься лише анімація kf-pulse. .bad-combo { анімація: kf-zoom 0,5 с вперед, kf-імпульс 1.2s нескінченний чергування; --kf-zoom-від: 0,5; --kf-zoom-to: 1,2; --kf-pulse-scale-from: 0,8; --kf-pulse-scale-to: 1,1; }
Доповнення анімації Найпростіший і найпряміший спосіб обробки кількох анімацій, які впливають на ту саму властивість, — це використовувати властивість animation-composition. В останньому прикладі вище анімація kf-pulse замінює анімацію kf-zoom, тому ми не побачимо початкового масштабу та не отримаємо очікуваний масштаб до 1,2. Встановлюючи композицію анімації для додавання, ми повідомляємо браузеру об’єднати обидві анімації. Це дає нам бажаний результат. .component-two { анімація-композиція: доп.; }
Дивіться маркери ключових кадрів пера - демо 8 [форк] від Аміта Шина. Цей підхід добре працює в більшості випадків, коли ми хочемо поєднати вплив на ту саму властивість. Це також корисно, коли нам потрібно поєднати анімації зі статичними значеннями властивостей. Наприклад, якщо у нас є елемент, який використовує властивість translate, щоб позиціонувати його саме там, де ми хочемо, а потім ми хочемо анімувати його за допомогою ключових кадрів kf-slide-in, ми отримаємо неприємний видимий стрибок без композиції анімації. Дивіться маркери ключових кадрів пера - демо 9 [форк] від Аміта Шина. Завдяки набору композиції анімації анімація плавно поєднується з наявноюtransform, щоб елемент залишався на місці та анімувався, як очікувалося. Анімація Інший спосіб роботи з декількома анімаціями полягає в тому, щоб «розташувати» їх, тобто почати другу анімацію трохи після завершення першої. Це не рішення, яке працює в кожному випадку, але воно корисне, коли у нас є анімація входу, за якою слідує безперервна анімація. /* згасання + імпульс непрозорості */ .notification { анімація: kf-fade-in 2s ease-out, kf-імпульс 0,5 с 2 с легкий вхід-вихід нескінченний поперемінний; --kf-pulse-opacity-to: 0,5; }
Перегляньте маркери ключових кадрів Pen - Демо 10 [forked] від Аміта Шина. Порядок має значення Значна частина анімацій, з якими ми працюємо, використовує властивість transform. У більшості випадків це просто зручніше. Він також має перевагу в продуктивності, оскільки анімацію трансформації можна прискорювати GPU. Але якщо ми використовуємо перетворення, нам потрібно визнати, що порядок, у якому ми виконуємо наші перетворення, має значення. багато. У наших ключових кадрах поки що ми використовували окремі трансформації. Відповідно до специфікацій, вони завжди застосовуються у фіксованому порядку: спочатку елемент отримує трансляцію, потім обертання, потім масштабування. Це має сенс, і більшість із нас цього очікує. Однак, якщо ми використовуємо властивість transform, порядок, у якому записуються функції, є порядком, у якому вони застосовуються. У цьому випадку, якщо ми перемістимо щось на 100 пікселів по осі Х, а потім повернумо це на 45 градусів, це не те саме, що спочатку повернути це на 45 градусів, а потім перемістити на 100 пікселів. /* Рожевий квадрат: спочатку перекладіть, потім обертайте */ .example-one { перетворення: translateX(100px) rotate(45deg); }
/* Зелений квадрат: спочатку повернути, потім перемістити */ .example-two { перетворення: rotate(45deg) translateX(100px); }
Дивіться маркери ключових кадрів Pen - демо 11 [forked] від Аміта Шина. Але згідно з порядком перетворення, усі окремі перетворення — все, що ми використовували для маркерів ключових кадрів — відбуваються перед функціями перетворення. Це означає, що все, що ви встановите у властивості transform, відбудеться після анімації. Але якщо ви встановите, наприклад, переклад разом із ключовими кадрами kf-spin, переклад відбудеться перед анімацією. Ще заплуталися?! Це призводить до ситуацій, коли статичні значення можуть викликати різні результати для тієї самої анімації, як у наступному випадку:
/* Загальна анімація для обох спінерів */ .spinner { анімація: kf-spin 1s linear infinite; }
/* Pink spinner: переклад перед обертанням (окреме перетворення) */ .spinner-pink { переклад: 100% 50%; }
/* Зелений оберіг: обертання, а потім переклад (порядок функцій) */ .spinner-green { transform: translate(100%, 50%); }
Дивіться маркери ключових кадрів Pen - демо 12 [forked] від Аміта Шина. Ви бачите, що перший спінер (рожевий) отримує трансляцію, яка відбувається перед поворотом kf-spin, тому він спочатку переміщується на своє місце, а потім обертається. Другий спінер (зелений) отримує функцію translate(), яка виконується після окремого перетворення, тому елемент спочатку обертається, а потім рухається відносно свого поточного кута, і ми отримуємо цей ефект широкої орбіти. Ні, це не помилка. Це лише одна з тих речей, які ми повинні знати про CSS і пам’ятати, коли працюємо з декількома анімаціями чи декількома трансформаціями. За потреби ви також можете створити додатковий набір ключових кадрів kf-spin-alt, які обертають елементи за допомогою функції rotate(). Зменшений рух І поки ми говоримо про альтернативні ключові кадри, ми не можемо ігнорувати опцію «без анімації». Одна з найбільших переваг використання маркерів ключових кадрів полягає в тому, що доступність може бути вбудована, і це насправді досить легко зробити. Розробляючи наші ключові кадри з урахуванням доступності, ми можемо гарантувати, що користувачі, які віддають перевагу зменшеному руху, отримають більш плавний, менш відволікаючий досвід, без додаткової роботи чи дублювання коду. Точне значення «Зменшеного руху» може дещо змінюватись від однієї анімації до іншої та від проекту до проекту, але ось кілька важливих моментів, про які слід пам’ятати: Вимкнення ключових кадрів Хоча деякі анімації можна пом’якшити або сповільнити, є інші, які мають повністю зникнути, коли запитується зменшення руху. Хорошим прикладом є анімація пульсу. Щоб переконатися, що ці анімації не працюють у режимі зменшеного руху, ми можемо просто обернути їх у відповідний медіа-запит.
@media (prefers-reduced-motion: no-preference) { @keyfrmaes kf-pulse { від { шкала: var(--kf-pulse-scale-from, 1); непрозорість: var(--kf-pulse-opacity-from, 1); } до { масштаб: var(--kf-pulse-scale-to, 1); непрозорість:var(--kf-pulse-opacity-to, 1); } } }
Це гарантує, що користувачі, які встановили параметр prefers-reduced-motion для зменшення, не бачитимуть анімацію та отримають досвід, який відповідає їхнім уподобанням. Миттєвий вхід Є деякі ключові кадри, які ми не можемо просто видалити, наприклад анімацію входу. Значення має змінюватися, оживляти; інакше елемент не матиме правильних значень. Але в скороченому русі цей перехід від початкового значення повинен бути миттєвим. Щоб досягти цього, ми визначимо додатковий набір ключових кадрів, де значення відразу переходить до кінцевого стану. Вони стають нашими ключовими кадрами за замовчуванням. Потім ми додамо звичайні ключові кадри всередину медіа-запиту для prefers-reduced-motion зі значенням no-preference, як у попередньому прикладі. /* миттєво з’являється для зменшення руху */ @keyframes kf-zoom { від, до { масштаб: var(--kf-zoom-to, 1); } }
@media (prefers-reduced-motion: no-preference) { /* Оригінальні ключові кадри масштабування */ @keyframes kf-zoom { від { масштаб: var(--kf-zoom-from, 0,8); } до { масштаб: var(--kf-zoom-to, 1); } } }
Таким чином, користувачі, які віддають перевагу зменшеному руху, побачать, як елемент миттєво з’явиться в кінцевому стані, а всі інші отримають анімований перехід. М'який підхід Бувають випадки, коли ми хочемо зберегти певний рух, але набагато м’якший і спокійніший, ніж оригінальна анімація. Наприклад, ми можемо замінити відбійний вхід на плавне затухання.
@keyframes kf-bounce { /* М'яке затухання для зменшення руху */ }
@media (prefers-reduced-motion: no-preference) { @keyframes kf-bounce { /* Оригінальні ключові кадри відскоку */ } }
Тепер користувачі з увімкненим обмеженням руху все одно відчувають зовнішній вигляд, але без інтенсивного руху підстрибування чи пружної анімації. Коли будівельні блоки готові, наступне питання полягає в тому, як зробити їх частиною фактичного робочого процесу. Написання гнучких ключових кадрів — це одне, але для того, щоб зробити їх надійними у великому проекті, потрібні кілька стратегій, які мені довелося освоїти важко. Стратегії впровадження та найкращі практики Коли у нас буде солідна бібліотека маркерів ключових кадрів, справжнє завдання полягає в тому, як застосувати їх у повсякденній роботі.
Спокуса полягає в тому, щоб скинути всі ключові кадри відразу й оголосити проблему вирішеною, але на практиці я виявив, що найкращі результати досягаються при поступовому застосуванні. Почніть із найпоширеніших анімацій, таких як зникнення або ковзання. Це легкі виграші, які демонструють негайну цінність, не вимагаючи великих переписів. Назви – ще один момент, який заслуговує на увагу. Послідовний префікс або простір імен робить очевидним, які анімації є маркерами, а які локальними одноразовими. Це також запобігає випадковим зіткненням і допомагає новим членам команди з першого погляду розпізнати спільну систему. Документація так само важлива, як і сам код. Навіть короткий коментар над кожним маркером ключового кадру може заощадити години вгадування пізніше. Розробник повинен мати можливість відкрити файл токенів, відшукати потрібний ефект і скопіювати шаблон використання прямо у свій компонент. Завдяки гнучкості цей підхід вартий зусиль. Розкриваючи розумні спеціальні властивості, ми даємо командам можливість адаптувати анімацію, не порушуючи систему. У той же час намагайтеся не ускладнювати. Забезпечте важливі ручки, а решта залишайтеся впевненими. Нарешті, пам’ятайте про доступність. Не кожна анімація потребує альтернативи зменшеного руху, але багато хто потребує. Завчасне внесення цих коригувань означає, що нам ніколи не доведеться їх модернізувати пізніше, і це свідчить про рівень турботи, який наші користувачі помітять, навіть якщо вони ніколи про це не згадуватимуть.
З мого досвіду, обробка токенів ключових кадрів як частини нашого робочого процесу дизайну токенів змушує їх залишатися. Коли вони встановлені, вони перестають виглядати як спеціальні ефекти та стають частиною мови дизайну, природним продовженням того, як продукт рухається та реагує. Підведення підсумків Анімація може бути однією з найприємніших частин створення інтерфейсів, але без структури вона також може стати одним із найбільших джерел розчарування. Розглядаючи ключові кадри як маркери, ви берете те, що зазвичай безладно і важко керувати, і перетворюєте це на чітку, передбачувану систему. Справжня цінність полягає не лише в збереженні кількох рядків коду. Упевненість полягає в тому, що коли ви використовуєте згасання, ковзання, масштабування або обертання, ви точно знаєте, як це поводитиметься в проекті. Вона полягає в гнучкості, яка приходить від настроюваних властивостей без хаосу нескінченних варіацій. І це в доступності, закладеній у основу, а не доданій якзапізніла думка. Я бачив, як ці ідеї працюють у різних командах і на різних кодових базах, і шаблон завжди однаковий. Коли маркери встановлені, ключові кадри перестають бути розрізненою колекцією прийомів і стають частиною мови дизайну. Вони роблять продукт більш навмисним, більш послідовним і більш живим. Якщо взяти одну річ із цієї статті, нехай це буде так: анімації заслуговують на таку ж увагу та структуру, яку ми вже надаємо кольорам, типографіці та інтервалам. Невеликі інвестиції в токени ключових кадрів окупаються щоразу, коли ваш інтерфейс змінюється.