Существует множество библиотек анимации JavaScript, но Anime.js — одна из лучших. Он прост в использовании, имеет небольшой и простой API и предлагает все, что вам нужно от современного движка анимации. Библиотека имеет небольшой размер файла и поддерживает все современные браузеры, включая IE / Edge 11+.
Единственное, что может помешать вам использовать Anime.js сразу же, это его минимальная, похожая на дзен документация. Мне нравится компактный, структурированный, элегантный подход, который требуется, но я думаю, что было бы полезно более подробное объяснение. Я постараюсь исправить эту проблему в этом уроке.
Начало работы с Anime.js
Для начала загрузите файл anime.js
и anime.js
в HTML-страницу:
<script src="path/to/anime.min.js"></script>
Кроме того, вы можете использовать последнюю версию библиотеки, размещенной на CDN:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/anime.min.js"></script>
Теперь, чтобы создать анимацию, мы используем функцию anime()
, которая принимает объект в качестве аргумента. В этом объекте мы опишем все детали анимации.
let myAnimation = anime({ /* describe the animation details */ });
Существует несколько видов свойств, используемых для описания анимации. Они сгруппированы в четыре категории:
- Цели — это включает ссылку на элемент (ы), которые мы хотим анимировать. Это может быть селектор CSS (
div
,#square
,.rectangle
), узел DOM или список узлов или простой объект JavaScript. Существует также возможность использовать сочетание вышеперечисленного в массиве. - Свойства — сюда входят все свойства и атрибуты, которые можно анимировать при работе с CSS, объектами JavaScript, DOM и SVG.
- Параметры свойства — сюда входят параметры, связанные со свойствами, такие как
duration
,delay
,easing
и т. Д. - Параметры анимации — это включает связанные с анимацией параметры, такие как
direction
,loop
и т. Д.
Давайте теперь посмотрим, как это применимо на практике. Рассмотрим следующий пример:
let animation = anime({ targets: 'div', // Properties translateX: 100, borderRadius: 50, // Property Parameters duration: 2000, easing: 'linear', // Animation Parameters direction: 'alternate' });
Примечание. Я не собираюсь рассказывать о разделах HTML и CSS в этом руководстве. Как правило, их легко понять без дополнительного объяснения. Вы можете найти и изучить HTML и CSS во встроенных ручках, которые следуют каждому примеру.
В приведенном выше примере:
- Мы выбираем зеленый квадрат (стилизованный
div
). - Мы перемещаем его на 100 пикселей влево, превращая его в круг.
- Мы установили, что все это происходит плавно в течение двух секунд (
linear
означает, что замедление не будет применено к анимации). - Устанавливая свойство direction для
alternate
, мы указываем элементуdiv
вернуться к своей начальной позиции и форме после завершения анимации. Anime.js делает это, воспроизводя анимацию в обратном порядке.
Вы можете заметить, что я не использую какие-либо единицы при указании значений свойств. Это потому, что если исходное значение имеет единицу измерения, оно автоматически добавляется к анимированному значению. Таким образом, мы можем смело опустить единицы. Но если мы хотим использовать конкретную единицу, мы должны добавить ее намеренно.
Давайте создадим что-то более значимое.
Создание анимации маятника
В этом примере мы создадим анимацию маятника. После того, как мы «нарисовали» маятник, используя наши навыки HTML и CSS, пришло время воплотить его в жизнь:
let animation = anime({ targets: '#rod', rotate: [60, -60], // from 60 to -60 degrees duration: 3000, easing: 'easeInOutSine', direction: 'alternate', loop: true });
В этой анимации мы используем так называемый тип значения from-to , который определяет диапазон движения анимации. В нашем случае стержень маятника поворачивается от 60
до -60
градусов. Мы также используем easeInOutSine
для имитации естественного движения маятника, который замедляется на пиках и ускоряется внизу. Мы снова используем alternate
опцию, чтобы переместить маятник в обоих направлениях и установили для параметра loop
значение true
чтобы бесконечно повторять движение.
Отлично сработано. Давайте перейдем к следующему примеру.
Создание анимации заряда батареи
В этом примере мы хотим создать анимированный значок зарядки аккумулятора, аналогичный значкам на наших смартфонах. Это легко сделать с небольшим количеством HTML и CSS. Вот код для анимации:
let animation = anime({ targets: '.segment', width: 20, duration: 300, delay: function(el, i, l) { return i * 500; }, endDelay: 500, easing: 'linear', loop: true });
Здесь у нас есть три сегмента (зеленые элементы div
), которые расширяются (путем увеличения свойства width
) один за другим. Чтобы достичь этого эффекта, нам нужно использовать разные задержки для каждого. Есть только один параметр задержки, который мы можем использовать для анимации, поэтому в этой ситуации мы собираемся использовать параметр на основе функции, который создает разные значения для каждой цели.
Для этого вместо литерального значения мы предоставляем функцию с тремя аргументами ( target
, index
и targetsLength
). В нашем случае функция возвращает индекс, умноженный на 500 миллисекунд, что заставляет каждый элемент начинать анимацию через полсекунды после предыдущего.
Мы также используем параметр endDelay
чтобы сделать паузу на мгновение, прежде чем анимация снова запустится.
Улучшение анимации зарядки аккумулятора
Теперь анимация выглядит хорошо, но давайте немного ее улучшим, добавив метку прогресса, показывающую процент заряда. Вот код:
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); } });
В этом примере представлены еще несколько функций библиотеки. Мы будем исследовать их один за другим.
Сначала мы создаем переменную progress
, которая ссылается на метку в HTML. Затем мы создаем объект battery
который содержит свойство progress
. Затем мы создаем две анимации.
Первая анимация практически идентична предыдущему примеру, за исключением параметра delay
. Здесь мы будем использовать функцию Anime.js, которая позволяет нам анимировать сразу несколько элементов. Для этого мы используем anime.stagger()
. В нашем случае anime.stagger(500)
работает так же, как параметр на основе функции — он добавляет задержку в 50 миллисекунд перед анимацией каждого элемента.
Во второй анимации мы используем объект battery
в качестве цели. Затем мы устанавливаем свойство progress
для анимации на 100%. Параметр round
округляет анимированное значение до заданного десятичного числа. Установив его на 1, мы получим целые числа.
Далее мы используем два из обратных вызовов, которые предлагает Anime.js.
Чтобы связать значение метки прогресса из HTML со значением прогресса battery
, мы используем обратный вызов update()
. Мы также используем обратный вызов complete()
чтобы остановить анимацию после того, как прогресс равен 100%, и мы используем метод seek()
чтобы установить анимацию в ее завершенное состояние.
В результате анимация зарядки будет воспроизводиться до тех пор, пока прогресс не станет равным 100%, а затем остановится и заставит сегменты перейти в конечное состояние анимации. Значок появится как полностью заряженный.
Создание более сложных анимаций с ключевыми кадрами
До сих пор мы имели дело с одношаговой анимацией, которая перемещает объект из А в В. Но как насчет перемещения его из А в В в С в D?
В следующем примере мы рассмотрим, как использовать ключевые кадры свойств для создания многошаговой анимации. Мы переместим простой квадрат вокруг другого, который служит в качестве коробки.
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"; } });
Сначала мы создаем ссылку на элемент box. Мы используем его в обратных вызовах begin()
и complete()
чтобы «открыть» окно в начале анимации и «закрыть» его в конце анимации. Давайте рассмотрим, как мы перемещаем другой квадрат — содержание.
Для каждого свойства, которое мы хотим анимировать, мы используем массив объектов, где каждый объект описывает определенный ключевой кадр.
В нашем случае мы хотим переместить квадрат вертикально и горизонтально. Поэтому мы используем свойства translateY
и translateX
и предоставляем массив ключевых кадров для каждого из них. Хитрость в создании правильного движения состоит в том, чтобы правильно рассчитать параметры duration
и delay
— что может быть непросто!
Кадры выполняются сверху вниз и запускаются одновременно для каждого свойства, имеющего указанный массив ключевых кадров. То, как будет продолжаться поездка, полностью зависит от того, как заданы параметры duration
и delay
. Удачи в вычислениях!
Результатом нашей анимации является то, что квадрат выходит из поля, делает вокруг него полную орбиту, а затем снова входит внутрь.
Создание текстовых эффектов
Мы видели пример ошеломляющего выше, и теперь мы рассмотрим более продвинутое использование. Мы будем использовать ошеломление, чтобы создать крутой текстовый эффект.
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] });
Мы поместили каждую букву в элемент span
. В коде анимации мы выбираем все буквы, делаем их видимыми и перемещаем их на 50 пикселей вниз.
Затем мы поворачиваем буквы, используя определенный параметр свойства, который определяет конкретные параметры для данного свойства. Это дает нам более детальный контроль над анимацией. Здесь буквы будут поворачиваться на 360 градусов за две секунды, применяя easeInExpo
.
В следующих двух свойствах мы используем функцию stagger()
. Мы устанавливаем масштаб для равномерного распределения от 0,7 до 1 непрозрачности (используя тип значения диапазона), начиная с центра (используя опцию начальной позиции). Это делает буквы меньше в середине предложения и больше на обоих концах.
Мы устанавливаем анимацию на ожидание секунды до ее запуска (путем определения начального значения), а затем добавляется задержка в 100 миллисекунд относительно каждой буквы.
Мы намеренно добавляем свойство translateX
в конце, чтобы создать желаемый эффект — вращать буквы по спирали.
Создание анимации с помощью временных шкал
Временная шкала позволяет вам одновременно управлять несколькими анимациями. Давайте рассмотрим простой пример:
let animation = anime.timeline({ duration: 1000, easing: 'easeInOutSine', direction: 'alternate', loop: true }); animation.add({ targets: '.one', translateY: -50, backgroundColor: 'rgb(255, 0, 0)' }).add({ targets: '.two', translateY: -50, backgroundColor: 'rgb(0, 255, 0)' }).add({ targets: '.three', translateY: -50, backgroundColor: 'rgb(0, 0, 255)' });
В этом примере мы создаем шариковый спиннер.
Чтобы создать временную шкалу, мы используем anime.timeline()
. Затем мы определяем общие параметры, которые наследуются для всех добавляемых анимаций.
Чтобы добавить анимацию на временную шкалу, мы используем метод add()
, а затем мы описываем анимацию так же, как мы уже рассмотрели.
В нашем примере мы добавляем три анимации, по одной на каждый шар. В результате каждый шар поднимается и опускается один за другим.
Проблема в том, что в этой базовой форме анимация кажется очень статичной. Давайте изменим это.
По умолчанию каждая анимация начинается после окончания предыдущей. Но мы можем контролировать это поведение, используя смещения времени. Также, если мы хотим сделать анимацию более гибкой и сложной, мы должны использовать ключевые кадры анимации. Давайте посмотрим, как это применимо в следующем примере:
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');
Здесь мы удаляем параметр direction
, потому что мы используем ключевые кадры для достижения движения вперед и назад. Мы определяем ключевые кадры анимации, добавляя параметр keyframes
. Как и в случае ключевых кадров свойств, каждый объект массива является ключевым кадром.
Чтобы шарики двигались плавно, мы используем временные смещения, которые указываются в качестве второго параметра функции add()
. В нашем случае мы используем значения относительно предыдущей анимации.
Результатом является плавная анимация вращающегося шарика.
Вывод
Я надеюсь, что вы получили лучшее понимание Anime.js. Чтобы продолжить обучение с этими базовыми знаниями, я рекомендую ознакомиться с документацией .
Anime.js — это простой, но мощный движок анимации, который можно использовать для создания широкого спектра анимаций. Дайте волю своему воображению.