Как сделать js анимацию с помощью Anime.js

JavaScript
14074
Как сделать js анимацию с помощью Anime.js
Active vision

Существует много JavaScript библиотек для веб анимации, и Anime.js одна из лучших. Ей легко пользоваться, у нее есть небольшой и простой API и она имеет все что нужно современному анимационному движку. Anime.js мало весит и поддерживает все современные браузеры, включая IE/Edge 11+.

Как сделать js анимацию с помощью Anime.js Как сделать js анимацию с помощью Anime.js

Единственное, что может вас остановить от использования Anime.js, так то ее скромная документация. Более подробные объяснения были бы полезней, но это мы постараемся исправить в этом уроке.

Anime.js — первая анимация

Для того, чтобы начать, скачаем и подключим anime.js файл в наш HTML код.


HTML
<script src="path/to/anime.min.js"></script>

Либо можно использовать последнюю версию, которая хостится на CDN.


HTML
<script src="https://cdn.jsdelivr.net/npm/animejs@3.0.1/lib/anime.min.js"></script>

Теперь, чтобы создать анимацию, мы будем использовать функцию anime(), которая принимает в качестве аргумента объект. В том объекте мы и будем описывать все детали нашей будущей анимации.


JS
let myAnimation = anime ({
  /* описание анимации */
});

Для описания анимации используется несколько свойств. Они сгруппированы в четыре различных категории:

  • Цели — это ссылки на элемент(ы), которые мы хотим анимировать. Это могут быть селекторы CSS (div, #myElem, .myClass), элемент DOM или простой объект JavaScript. Можно также использовать все вышеперечисленное в массиве.
  • Свойства — сюда включены свойства и атрибуты, которые могут быть анимированы при работе с объектами CSS, JavaScript, DOM и SVG.
  • Параметры свойств — в эту категорию включены связанные со свойствами параметры, такие как длительность, задержка, замедление и т.д.
  • Параметры анимации — связанные с анимацией параметры, такие как направление, цикл и т.д.

Посмотрим как это применяется на практике.


JS
let animation = anime({
  // Цели
  targets: 'div',
  // Свойства
  translateX: 100,
  borderRadius: 50,
  // Параметры свойств
  duration: 2000,
  easing: 'linear',
  // Параметры анимации
  direction: 'alternate'
});

See the Pen AnimeJS: Basic Example by active-vision (@dmitriybelov) on CodePen.

Мы сделали нашу первую js анимацию. В приведенном выше примере:

  • Мы выбираем зеленый квадрат (стилизованный div).
  • Мы перемещаем его на 100 пикселей влево и преобразуем его в круг.
  • Устанавливаем duration: 2000, чтобы все это происходит плавно в течение двух секунд, linear означает, что к анимации не будет применено замедление.
  • Установив свойство direction в значение alternate, мы даем команду элементу div вернуться в исходное положение и форму после завершения анимации. Аниме.js делает это, воспроизводя анимацию в обратном порядке.

Вы можете заметить, что мы не используем никаких единиц измерения, потому что они добавляются автоматически. Но если вы хотите использовать специфические единицы измерения, можно намеренно их указать.

Давайте создадим более значимую анимацию.

Анимация маятника

В этом примере мы создадим анимацию маятника, нарисуем его используя наши навыки HTML и CSS.


JS
let animation = anime({
  targets: '#rod',
  rotate: [60, -60], // от 60 до -60 градусов
  duration: 3000,
  easing: 'easeInOutSine',
  direction: 'alternate',
  loop: true
});

See the Pen AnimeJS: Pendulum Animation by active-vision (@dmitriybelov) on CodePen.

В этой анимации мы определяем диапазон движения для анимации, маятник поворачивается от 60 до -60 градусов. Мы также используем замедление easeInOutSine для имитации естественного движения маятника, который замедляется на пиках и становится быстрее в нижней точке. Также мы снова указали параметр direction: loop для вращения маятника в обоих направлениях и loop: true чтобы бесконечно повторять движение.

Давайте перейдем к следующему примеру.

Js анимация зарядки аккумулятора

В этом примере мы создадим анимированную иконку зарядки батареи, похожую на ту, что в наших смартфонах. Это легко сделать, используя небольшое количество HTML и CSS. Вот код анимации:


JS
let animation = anime({
  targets: '.segment',
  width: 20,
  duration: 300,
  delay: function(el, i, l) {
    return i * 500;
  },
  endDelay: 500,
  easing: 'linear',
  loop: true
});

See the Pen AnimeJS: Charging Battery Animation by active-vision (@dmitriybelov) on CodePen.

Мы создали 3 элемента div с классом segment, которые расширяются (width: 20) один за другим. Для достижения эффекта зарядки нам нужно использовать разные задержки для каждого сегмента. Параметр delay у нас только один, поэтому в этой ситуации мы будем использовать параметр на основе функции, который создает разное значение для каждой цели.

Для этого вместо одного значения мы предоставляем функцию с тремя аргументами (target, index и targetsLength). В нашем случае функция возвращает index, умноженный на 500 миллисекунд, что заставляет каждый элемент начать анимацию через полсекунды после предыдущего.

Также мы используем параметр endDelay для приостановке анимация перед повторным запуском.

Улучшаем анимацию зарядки аккумулятора

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


JS
let progress = document.querySelector('#progress');
let battery = {
  progress: '0%' 
}
let icon = anime({
  targets: '.segment',
  width: 20,
  duration: 300,
  delay: anime.stagger(500),
  endDelay: 500,
  easing: 'linear',
  loop: true
}); 
let label = anime({
  targets: battery,
  progress: '100%',
  duration: 30000,
  easing: 'linear',
  round: 1,
  update: function() {
    progress.innerHTML = battery.progress
  },
  complete: function() {
    icon.pause();
    icon.seek(icon.duration);
  }
});

See the Pen AnimeJS: Improved Charging Battery Animation by active-vision (@dmitriybelov) on CodePen.

Для начала мы создаем переменную progress, которая ссылается на элемент #progress в HTML. Затем создаем объект battery, который содержит свойство progress. И далее создаем две анимации.

Первая анимация практически идентична предыдущему примеру, за исключением параметра delay. Здесь мы будем использовать Anime.js фичу, которая позволит нам анимировать сразу несколько элементов. Для этого будем использовать функцию anime.stragger(). В нашем случае anime.stagger(500) работает так же, как параметр на основе функции-он добавляет 50—миллисекундную задержку перед каждым элементом анимации.

Во второй js анимации, в качестве target будем использовать объект battery. Затем мы устанавливаем свойство прогресса для анимации 100%. Параметр round округляет анимированное значение до заданного десятичного числа. Установив его в 1, мы получаем целые числа.

Далее, мы используем две callback функции Anime.js.

Чтобы связать значение метки прогресса из HTML со значением прогресса батареи, мы используем callback update(). Мы также используем callback complete(), чтобы остановить анимацию после того, как прогресс будет равен 100%, и мы используем метод seek(), чтобы установить анимацию в ее завершенное состояние.

В результате анимация зарядки будет воспроизводиться до тех пор, пока прогресс не станет 100%, а затем он остановится и батарея придет к финальному состоянию анимации. Значок будет отображаться как полностью заряженный.

Более сложные js анимации с кейфреймами

До сих пор мы имели дело с анимациями в один шаг, которые перемещали объект из точки А в точку Б. А как на счет перемещения его из А в Б, а потом в В и Г?

В следующем примере мы рассмотрим как использовать кейфреймы для создания многоступенчатой js анимации. Мы будем перемещать обычный квадрат вокруг другого, который будет служить в качестве коробки.


JS
let box = document.querySelector('#box'); 
let animation = anime({
  targets: '#content',
  translateY: [
    {value: 50, duration: 500},
    {value: 0, duration: 500, delay: 1500},
    {value: -53, duration: 500, delay: 500},
    {value: 0, duration: 500, delay: 2500},
    {value: 50, duration: 500, delay: 500},
    {value: 0, duration: 500, delay: 1500}
  ],
  translateX: [
    {value: 53, duration: 500, delay: 1000},
    {value: 0, duration: 500, delay: 2500},
    {value: -53, duration: 500, delay: 500},
    {value: 0, duration: 500, delay: 2500}
  ],
  easing: 'linear',
  begin: function() {
    box.style.borderBottom="none";
  },
  complete: function() {
    box.style.borderBottom="solid darkorange 3px";
  }
});

See the Pen AnimeJS: Box Animation With Keyframes by active-vision (@dmitriybelov) on CodePen.

Для начала создадим ссылку на элемент #box. Мы будем использовать его в коллбэках begin() и complite(), чтобы "открыть" коробку при запуске анимации и закрыть ее в конце анимации. Давайте рассмотрим как мы будем перемещать другой квадрат.

Для каждого свойства, которое мы хотим анимировать, мы используем массив объектов, где каждый объект описывает определенный кейфрейм.

В нашем случае мы хотим переместить квадрат вертикально и горизонтально. Поэтому мы используем свойства translateY и translateX и описываем массив кейфреймов для каждого из них. Важно правильно вычислить параметры длительности и задержки, это может быть трудно.

Кадры исполняются сверху вниз и запускаются одновременно для каждого свойства, которое имеет указанный массив кейфреймов. Ход анимации будет полностью зависеть от того как установлены параметры delay и duration. Удачи с вычислениями!

Результатом нашей анимации является то, что квадрат выходит из коробки, делает полный оборот вокруг нее, а затем снова входит внутрь.

Создание текстовых эффектов

Выше мы рассмотрели разные примеры простой анимации, настало время сделать js анимацию классного текстового эффекта.


JS
let animation = anime({
  targets: '.letter',
  opacity: 1,
  translateY: 50,
  rotate: {
    value: 360,
    duration: 2000,
    easing: 'easeInExpo'
  },
  scale: anime.stagger([0.7, 1], {from: 'center'}),
  delay: anime.stagger(100, {start: 1000}),
  translateX: [-10, 30]
});

See the Pen AnimeJS: Text Effect Animation by active-vision (@dmitriybelov) on CodePen.

Мы поместили каждую букву внутри элемента span. В коде анимации мы выбираем все буквы, делаем их видимыми и перемещаем их на 50 пикселей вниз.

Затем мы поворачиваем буквы на 360 градусов за две секунды, применяя easeInExpo.

В следующих двух свойствах мы используем функцию stagger(). Мы устанавливаем scale от 0,7 до 1 (используя тип значения диапазон), от центра (используя параметр начальной позиции). Это делает буквы меньше в середине предложения и больше на обоих концах.

Мы заставляем подождать секунду, прежде чем она начнется (определив начальное значение), а затем 100-миллисекундная относительная задержка добавляется для каждой буквы.

Мы намеренно добавляем свойство translateX в конце, чтобы создать эффект вращения букв по спирали.

Анимации с таймлайнами

Таймлайны позволяют управлять сразу несколькими анимациями. Рассмотрим простой пример:


JS
let animation = anime.timeline({
  duration: 1000,
  easing: 'easeInOutSine',
  loop: true
});
animation.add({
  targets: '.one',
  keyframes: [
    {translateY: -50, backgroundColor: 'rgb(255, 0, 0)' },
    {translateY: 0, backgroundColor: 'rgb(128, 128, 128)'}
  ]
}).add({
  targets: '.two',
  keyframes: [
    {translateY: -50, backgroundColor: 'rgb(0, 255, 0)' },
    {translateY: 0, backgroundColor: 'rgb(128, 128, 128)'}
  ]
}, '-=900').add({
  targets: '.three',
  keyframes: [
    {translateY: -50, backgroundColor: 'rgb(0, 0, 255)' },
    {translateY: 0, backgroundColor: 'rgb(128, 128, 128)'}
  ]
}, '-=800');

See the Pen AnimeJS: Balls Spinner Timeline Animation by active-vision (@dmitriybelov) on CodePen.

Мы не будем использовать параметр direction, потому что мы используем кейфреймы для движения вперед и назад. Мы определяем кейфреймы анимации, добавляя параметр keyframes. Как и в предыдущем примере, каждый объект из массива является кейфреймом.

Чтобы шары двигались плавно, мы используем временные смещения, которые задаются в качестве второго параметра функции add(). В нашем случае, мы используем значения относительно предыдущей анимации.

В результате получается плавная анимация движения шаров.

В заключении

Надеюсь у вас сложилось представление о Anime.js. Аниме.js — это простой, но мощный анимационный движок, который может быть использован для создания широкого спектра анимаций. Осталось только дать волю вашему воображению!

Написать комментарий