От автора: если вы ищите быструю и легкую библиотеку для анимации, вам стоит обратить внимание на Anime.js Джулиана Гарньера. Эта статья будет первой в серии о динамической анимации в DOM и SVG графике. Я не буду вам рассказывать про canvas-WebGL библиотеки или специальные библиотеки для анимации в SVG. Но если библиотека действительно хорошо анимирует HTML элементы на странице (в идеале и SVG графику), я рассмотрю ее и включу в эту серию.
Я не собираюсь разбирать все библиотеки на запчасти и копаться в коде. Вместо этого я буду рассматривать все библиотеки с точки зрения человека, который в основном работает с CSS, но хотел бы узнать, что ему может предложить JS в плане анимации DOM. Поэтому я буду искать инструменты, которые отлично манипулируют DOM, динамически добавляя и удаляя CSS стили и/или классы для создания анимации, с синтаксисом, который будет знаком CSS разработчику.
Анимация в вебе
Как объясняет Сара Драснер, в веб-анимации нужно различать анимацию интерфейса/пользовательского опыта и независимую анимацию.
Исследование доказало, что человек намного лучше воспринимает мир на основе движущихся изображений. То есть мы лучше понимаем и усваиваем информацию, когда она представлена в виде чего-то движущегося, а не в форме простых изображений или серии статичных изображений.
UI/UX анимация помогает пользователю перемещаться по сайту, впитывать информацию на страницах и выполнять определенные задачи. Например, подписка на новостную рассылку, добавление товаров в корзину и т.д.
В противоположность этому независимая анимация… «Используется для иллюстрации концепции в теле страницы, вместе с ней или отдельно.» Сара Драснер – из слайдов с конференции по CSS
Сара иллюстрирует свою мысль в CodePen демо.
Разница очень важна. Во время анимации интерфейса вы стараетесь помочь пользователям выполнить определенные действия, которые согласуются с целями сайта. А при создании независимой анимации вы максимально полно пытаетесь раскрыть определенную концепцию.
Тем не менее, оба типа анимации должны приносить людям удовольствие. Вот почему при создании анимации все упирается в производительность и доступность. Эти факторы являются следствием анимации, которая будет восхищать, раздражать или даже причинять боль.
Зачем использовать JavaScript анимацию?
Сегодня CSS может нам предложить плавные переходы и анимацию. Однако JS до сих пор занимает первенство в вопросе создания анимации. Но почему? Мы уже сейчас можем делать анимацию на чистом CSS, зачем кому-либо использовать для этого JS?
Дабы помочь вам в выборе между CSS и JS Рэйчел Наборс составила список отличий. Анимация может быть:
Статичной: анимация от начала и до конца проходит без какой-либо логики ответвления. В качестве примера можно привести загрузчики на CSS. Такую анимацию можно написать на чистом CSS;
С сохранением состояния: хороший пример – сайдбар, который открывается и закрывается по клику на кнопку. Такой тип анимации можно написать на CSS с мелкими вкраплениями JS для добавления и удаления классов, отвечающих за состояния анимации;
Динамической: такая анимация может заканчиваться по-разному. Это зависит от действий пользователя, событий в DOM, состояний анимации других элементов в документе и т.д. Такой тип анимации нельзя создать с помощью CSS, тут ваш лучший друг – JS.
Помимо динамической анимации JS можно использовать, если вы попали в одну из следующих ситуаций:
вам нужно сцепить или разбить анимацию на большее количество элементов. В таком случае каждая анимация должна начинаться после завершения предыдущей. Это можно сделать и на чистом CSS, прописав везде свойство delay. Но если вам понадобится заменить всего одно значение, крайне неудобно переписывать все остальные;
вы хотите анимировать SVG графику. Тут главный минус в том, что CSS анимация в SVG неодинаково поддерживается во всех браузерах;
если ваш проект должен поддерживать старые браузеры, где не работает CSS анимация, надежное решение на JS обеспечит хорошую поддержку.
Более подробно по этой теме можно почитать в статье Развенчание мифов: CSS анимация или JS Джека Дойла, автора Greensock Animation Platform. Там он приводит пару хороших аргументов.
Перспективная замена: Web Animations API
W3C работает над спецификацией, которая объединит вместе CSS, SVG и JS анимацию в один унифицированный язык без необходимости подключения дополнительных JS библиотек. API называется Web Animations и отлично подходит для создания динамической анимации, где CSS не может ничего противопоставить. Можете прочитать полезную вступительную статью в Web Animations API от Дадли Стори прямо на сайте SitePoint.
Работа над Web Animations API ведется достаточно устойчивыми темпами, а для браузеров, которые не поддерживают API, есть полифил.
Звучит все круто, и я активно призываю всех экспериментировать с WAAPI. Тем не менее, на момент написания статьи поддержка в браузере разношерстная, а в спецификацию еще могут быть внесены изменения. Так что если WAAPI прямо сейчас не подходит для вашего проекта, можете переключиться на JS библиотеки.
Библиотеки для динамической анимации DOM
В сети полно JS библиотек для анимации. На момент написания статьи самыми популярными считались GreenSock или GSAP (GreenSock Animation Platform) и Velocity.js.
Обе библиотеки очень хороши и user-friendly. О них я расскажу отдельно в будущих статьях. А начать серию статей я хотел бы с Anime.js, новой JS библиотеки для анимации, набравшей большую популярность.
Главные возможности Anime
Название Anime произошло от японской анимации, компьютерной и ручной Anime.js… «гибкая, но легкая JS библиотека для анимации. Работает с CSS, Individual Transforms, SVG, атрибутами DOM и JS объектами.»
Anime.js поддерживает следующие браузеры: Chrome, Safari, Opera, Firefox, Internet Explorer 10+
Столько библиотек, почему именно Anime?
Ответ на этот вопрос лучше дать автору Anime. Как он объясняет, как он пришел к Anime.js, когда есть мощная библиотека GSAP:
«GSAP способен на гораздо большее, чем Anime. Но эта библиотека гораздо тяжелее. Моя цель была – сохранить простоту API, сосредоточиться на том, что мне реально нужно (несколько таймингов, функции анимации, элементы управления воспроизведением…), поддерживая максимально низкий вес (9Кб в минифицированном виде).»
Hacker News
Если коротко, Anime отлично подойдет вам, если вам нужно создать динамическую анимацию HTML и SVG элементов, в которой не нужны все возможности GSAP или других больших библиотек.
Как использовать Anime.js
Ниже я записал пару строк кода, иллюстрирующих как подключить Anime.js. Большинство анимации будет замедлено в демонстрационных целях.
Подключение Anime.js ничем не отличается от JQuery или любой другой JS библиотеки.
Скачайте файл .zip со страницы проекта на GitHub, извлеките файлы и пропишите anime.min.js в теге script внутри html:
1 |
<script src="anime.min.js"></script> |
Или можно сделать это в npm или bower:
1 2 |
npm install animejs bower install animejs |
Одна анимация на одном элементе: прыгающий мяч
После установки Anime.js в проект можно начать с самого простого типа анимации: просто один элемент, мяч, скачущий вверх и вниз. Первый шаг – вызвать anime, передав объект с набором настроек анимации. Стандартная структура:
1 2 3 4 5 |
var bouncingBall = anime({ //код }); |
Теперь необходимо конкретизировать объект, наполнив его инструкциями о том, что анимировать, виде анимации, ее продолжительности и т.д.
1 2 3 4 5 6 7 8 |
var bouncingBall = anime({ targets: '.ball', translateY: '50vh', duration: 300, loop: true, direction: 'alternate', easing: 'easeInCubic' }); |
Свойство targets отвечает в Anime за элемент, который необходимо анимировать. Можно указать CSS селектор, как это сделал я выше, или один из вариантов ниже:
элемент DOM, например, document.querySelector(‘.ball’);
Nodelist, например, document.querySelectorAll(‘.ball’);
JS объект, например, {elementName: ‘ball’};
JS массив, например, [‘.ball’].
Если в свойстве targets необходимо прописать более одного значения, то есть вы собираетесь применить анимацию к нескольким элементам, можно использовать массив:
1 2 3 4 |
var bouncingBall = anime({ targets: ['.ball', '.kick'], //код }); |
Второе свойство в примере выше перемещает элемент по вертикали с помощью translateY, данное свойство будет знакомо тем, кто работал с CSS. Тиффани Браун и другие разработчики советуют использовать translate и scale для перемещения и изменения размеров элементов, а не свойства, отвечающие за позицию элемента, ширину или высоту. Такой подход повышает производительность и качество анимации, так как страница в браузере не перестраивается заново.
Следующее свойство в примере выше – duration. Оно отвечает за продолжительность анимации в Anime. Если у вас в разные промежутки времени задействовано несколько анимаций, вам также пригодится свойство delay.
Свойство loop в Anime отвечает за количество повторений анимации. По умолчанию оно задано в false, то есть анимация запускается один раз. Анимацию можно зациклить при помощи значения true, также можно задать точное число повторений, указав необходимое число.
Свойство direction, представленное как в CSS, так и в Anime, можно установить в те же значения, что есть в CSS двойнике: normal, reverse и alternate. Последнее значение переключает ход анимации с нормального на противоположный, отлично подойдет для прыгающего мяча.
И наконец, последнее свойство в коде – easing. Скорость анимации должна быть постоянной? Может быть, анимация должна начинаться медленно и ускоряться к концу? Нужно ли в конце добавить отскок? Правильная функция анимации – один из ключевых ингредиентов отполированной и эффектной анимации.
Все функции анимации можно посмотреть с помощью кода ниже:
1 |
console.log(anime.easings); |
Добавляем вторую анимацию к прыгающему мячу
Скажем, вы хотите, чтобы мяч слегка сжимался при ударе о нижнюю границу контейнера. В Anime это можно сделать, добавив специальные параметры анимации в форме JS объекта. На примере мяча, вот так это можно сделать:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var bouncingBall = anime({ targets: '.ball', translateY: '50vh', duration: 300, loop: true, direction: 'alternate', easing: 'easeInCubic', //новый код scaleX: { value: 1.05, duration: 150, delay: 268 } }); |
В коде выше добавлено новое свойство scaleX, которое делает мяч шире. Само значение задается в форме объектного литерала с определенными ключами, с помощью которых можно контролировать анимацию.
Ключ value позволяет менять ширину элемента по горизонтальной оси, а duration и delay отвечают за продолжительность анимации и точку старта после завершения предыдущей анимации.
Если проинспектировать элемент в любимой панели разработчика, можно увидеть, как Anime анимирует элемент, добавляя инлайновый атрибут style и динамически обновляя значения свойства transform.
Последовательная анимация двух элементов: пинаем мяч
Код ниже – один из примеров того, как можно анимировать два элемента. В нашем случае это два изображения. Вторая анимация начинается после завершения первой.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var kickBall = anime({ targets: '.kick', scale: 1.2, duration: 300, easing: 'easeInCubic', complete: function() { anime({ targets: '.ball', translateX: '70vw', scale: 1.5, easing: 'easeOutBounce', delay: 150 }); } }); |
Мяч начинает двигаться только после удара. В Anime.js можно указать дополнительную анимацию при помощи метода complete(), в котором, в нашем случае, хранится второй объект с инструкциями для анимации мяча.
Конечно, в CSS можно создать статичную версию анимации. Понадобится несколько keyframe’ов и причудливая кубическая функция Безье. В таком случае JS вообще не нужен, а анимация будет плавная и будет работать нативно. Демо на чистом CSS:
Включаем, ставим на паузу и перезапускаем анимацию
Anime.js позволяет запускать, останавливать и перезапускать анимацию при помощи методов .play(), .pause() и .restart(). К примеру, вот так можно контролировать анимацию удара мяча.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
//Анимация удара var kickBall = anime({ targets: '.kick', scale: 1.2, duration: 300, delay: 100, easing: 'easeInCubic', autoplay: false }); //Анимация мяча var movingBall = anime({ targets: '.ball', translateX: '70vw', scale: 1.5, easing: 'easeOutBounce', delay: kickBall.duration + 100, autoplay: false }); /* Проигрываем анимацию when clicking the play button */ btnPlay.addEventListener('click', function(e) { e.preventDefault(); kickBall.play(); movingBall.play(); }); |
В коде нужно сделать пару замечаний:
чтобы контролировать и удар, и мяч с помощью кнопок, я создал два разных объекта. Можно было бы вложить анимация мяча в анимацию удара, но опыт показал, что тогда кнопка контролирует только главную анимацию, т.е. удар;
чтобы анимация автоматически не запускалась после полной загрузки страниц, необходимо задать autoplay в false;
и наконец, чтобы запустить анимацию, достаточно вызвать метод .play() на объектах kickBall и movingBall.
Запуск анимации и паузу можно быстро воссоздать с помощью CSS свойства animation-play-state и щепотки JS. Однако данным способом не получится воссоздать повторный запуск анимации после ее завершения или запустить обратную анимацию из любой точки.
Анимируем инлайновые атрибуты SVG с помощью Anime.js
В последнем демо показано, как анимировать атрибуты инлайновой SVG графики. В этот раз в качестве примера будет милый котенок, играющийся с мячом.
В демо используются классы CSS для разных путей и формы, из которых нарисован SVG котенок. Так намного легче искать элементы в коде.
Вот так можно анимировать глаз кота:
1 2 3 4 5 6 7 8 9 10 |
var movingEyes = anime({ targets: ['.inner-left-eye', '.inner-right-eye'], cy: 400, duration: 500, delay: function(el, index) { var singleDelay = index === 0 ? 300 : index * 500; return singleDelay; }, Autoplay: false }); |
Код выше опускает глаз кота, изменяя значение атрибута cy круга – зрачка кота.
Если вы заметили, то глаза двигаются последовательно. Я специально сделал так, чтобы показать вам еще один способ создания последовательной анимации в Anime.js. Свойство delay может быть числом, но также и функцией. Если использовать функцию, как в коде выше, вы можете программно контролировать старт анимации. Функция проверяет, если элемент, который необходимо анимировать, первый (на нулевой позиции в массиве targets), т.е. левый глаз, то анимация будет с задержкой в 300ms. Если элемент не первый, то задержка будет результатом умножения индекса элемента (т.е. 1) на 500ms.
Заключение
Я начал эту статью с краткого обзора, как анимация используется в вебе. Дальше мы обсудили, когда использовать JS, а когда CSS анимацию. Бегло прошлись по Web Animations API.
Также я представил вам Anime.js, первую библиотеку в этой серии. Я показал вам ее возможности и создал демо.
Мне очень нравится работать с Anime.js: ее возможности покрывают много способов применения, синтаксис довольно простой, а также с помощью библиотеки можно создавать плавные, красивые эффекты.
Для тех, кто раньше не знал про эту библиотеку, скажу, что единственная документация – это файл README.md на GitHub.
В разделе вопросов на GitHub вы найдете некоторые ответы для себя. За темой активно следит создатель Anime, Джулиан Гарньер.
Понять, как использовать библиотеку также можно из кода демо, в основе анимации которых лежит Anime. Если вы уже работали с Anime.js и хотите поделиться своим опытом, или же хотите предложить свои любимые библиотеки по анимации для этой серии статей, пишите об этом в комментариях.
Автор: Maria Antonietta Perna
Источник: //www.sitepoint.com/
Редакция: Команда webformyself.