Тарифы Услуги Сим-карты

Js анимация движения. JavaScript плагины для анимации. Реверсивные функции ease

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

Привет, друзья! В этой статье я предлагаю Вам ознакомиться с моей подборкой замечательных CSS-библиотек и JS-плагинов, которые помогут реализовать максимально совместимую анимацию на вашем сайте за считаные минуты.

JavaScript плагины для анимации

Если Вы хотите создавать анимации, которые запускаются по какому-нибудь событию или действию, то JavaScript плагины для анимации Вам очень сильно в этом помогут. Но стоит заметить, что большинство из этих анимаций написаны на CSS3, а управление ими происходит с помощью JavaScript.

AniJS

Dynamics.js

Dynamic.js - это JavaScript библиотека для создания анимаций на основе физики.

mo.js

mo.js - отличная библиотека для создания motion-графики. Пример такой графики вы встречали часто, когда Google размещал новый тематический логотип (doodle), который анимировался при наведении или клике.

cta.js

cta.js - JavaScript плагин для создания анимированных призывов к действию. Многие из них выглядят очень эффектно.

animo.js

animo.js - мощный инструмент для управления CSS3 анимациями.

html5tooltips.js

html5tooltips.js - старые добрые подсказки с современным дизайном и анимацией без зависимостей, подключил и используй.

Rocket

Rocket - интересная JS-библиотека, позволяющая анимировать путь элемента к цели.

scrollReveal.js

scrollReveal.js - плагин, позволяющий анимировать элементы при скролле страницы.

Wow.js

Wow.js - еще один javascript плагин для контроля анимации при скролле страницы.

Transit

Transit - jQuery-плагин для сглаживания переходов и трансформаций, предусмотренных в jQuery.

parallax.js

parallax.js - плагин, реагирующий на положение смартфона в пространстве, опираясь на это, управляет отступами, положением и глубиной слоев. Если же, устройство не имеет гироскоп, то вычисления берутся на основе положения курсора мыши. Двумя словами - продвинутый параллакс!

Sly

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

Move.js

Move.js - небольшая JavaScript библиотека для создания настроенных CSS3-анимаций.

slidr.js

slidr.js - простая в использовании и легковесная JavaScript библиотека для создания вертикального и одновременно горизонтального слайдера.

CreateJS

CreateJS - это набор модульных библиотек и инструментов, которые могут работать вместе или независимо друг от друга, для обагощения интерактивности контенту. Функционал этих библиотек позволит создавать потрясающие сайты и приложения, обязательно ознакомтесь с демками.

Flippant.js

Flippant.js - JavaScript-плагин для создания элементов с эффектом поворота вокруг своей оси.

jmpress.js

jmpress.js - JavaScript-библиотека с уникальной идеей создания сайта на бесконечном HTML5 canvas"е. Идея достойна внимания.

CSS3 библиотеки

Опытные разработчики уже достаточно давно позаботились о том, чтобы создать для нас библиотека с CSS3-анимациями. Теперь мы можем просто брать их и применять в своих проектах, и быть уверенными в их эффективности.

С появлением CSS3-анимаций, HTML-документы стали гораздо привлекательней, и разрабатывать их стало проще. Используя правило @keyframes, вы можете без труда определять различные параметры, включая расположение и размер HTML-элемента. Параметр animation, в свою очередь, отвечает за запуск и перемещение ключевых кадров в зависимости от определенных параметров. Без необходимости использовать javascript и плагины, мы можем без труда создавать даже самые сложные анимации, которые будут работать очень плавно во всех современных браузерах.

Проблемы возникают тогда, когда для разработки CSS3-анимаций вам необходимо использовать javascript. Все мы знаем, что javascript в большинстве случаев – это первая необходимость, которая позволяет нам вычислять отдельные значения или анимационный процесс в целом.

Комбинируем CSS и javascript при помощи нового метода animate()

Новый javascript-метод animate() позволяет нам управлять анимациями посредством скрипта. Конечно же, нам все равно нужно использовать целую пачку CSS-параметров для определения наших ключевых кадров.


{height: "0"},
{height: "100%"}
], {
duration: 3000,
iteration: 2,
delay: 1000
});
В вышеприведенном примере мы прикрепляем метод animate() к элементу. Внутри квадратных скобок определяется столько состояний заданного параметра, сколько нам требуется, и в нашем примере мы будем работать над height. Каждое значение записано в виде буквы объекта, а значения используются лишь для одного отдельного параметра. Комбинации вроде width и height недопустимы. Учтите, что сами значения должны быть обрамлены цитированием, и оформлены синтаксисом, отвечающим требованиям javascript, а это значит, что нужно использовать “backgroundColor” вместо “background-color”. В другой букве объекта, сразу после закрытия квадратных скобок, мы определяем дальнейшую анимацию. Мы хотим изменить длину анимацию посредством duration, частоту повторений посредством iteration и может на усмотрение определить задержку посредством параметра delay, - этот параметр определяет момент, когда должна быть запущена анимация. Все временные значения указываются в миллисекундах.

Управляем набором ключевых кадров и их продолжительностью

Нам нужно запустить метод animate() отдельно от каждого параметра, который нам нужно изменить. Это значит, что при желании изменить как height, так и width, нам нужно будет повторно запускать animate().

Document.getElementById("element").animate([
{width: "0", offset: 0},
{width: "10%", offset, 1/3},
{width: "100%", offset: 1}
], {
duration: 3000,
iteration: 2,
delay: 1000
});
Вы вышеприведенном примере мы изменяем ширину элемента. Ширина должна изменяться, начиная от 0, и поднимаясь до 10 процентов, а затем завершиться при достижении 100 процентов. Все это будет сопровождаться плавной анимацией, естественно. Дополнительный параметр offset определяет, что изменения от 0 до 10 процентов будут занимать 1/3 всего времени, а переход от 10 к 100 займет 2/3 всего времени анимации. И при этом всем, общая продолжительность анимации определяется параметром duration. В данном случае, первая часть будет происходит на протяжении одной секунды, а вторая – на протяжении 2.

Вместо того, чтобы определять значение в виде дробей, вы также можете воспользоваться десятичными числами. Нужно использовать цифры от 0 до 1. К примеру, вместо 1/3 вы можете использовать 0.33.

Больше опций для анимации

Если вы знакомы с CSS3-параметром animation, то наверняка знаете о том, что метод animate() позволяет управлять процессом анимации. Вы можете изменять направление, а также скорость анимации, и ее ускорение. Если вы хотите указать, что после окончания, анимация должна вернуться к началу, то можете сделать это.

Document.getElementById("element").animate([

], {
duration: 3000,
iteration: 2,
delay: 1000,
direction: "reverse",
easing: "ease-in",
fill: "forwards"
});
Значение direction содержит в себе информацию о направлении анимации. Если вы установите значение reverse, то анимация будет воспроизведена в обратном направлении. Значение же alternate позволит вам воспроизвести анимацию в стандартном направлении, а затем в обратном. А значение alternate-reverse комбинирует два последних значения.

Значение easing позволяет вам использовать самые распространенные функции модификаций, которые уже хорошо известны по CSS3, так как там можно встречать ease-in, ease-out и так далее. По умолчанию, каждая анимация настроена на линейный ход без ускорения или замедления. Значение fill определяет, что будет представлено после окончания анимации. По умолчанию, анимация должна вернуться к стартовой точке. При использовании значения forward, анимация остановится на последнем ключевом кадре.

Управление анимацией

Применение animate() к переменной позволяет нам управлять анимацией посредством javascript. Мы можем запускать и останавливать ее по собственному усмотрению.

Var animation = document.getElementById("element").animate([
{height: "0"},
{height: "100%"}
], {
duration: 3000,
iteration: 2,
delay: 1000
});

document.getElementById("animation_start").addEventListener("click", function() {
animation.play();
}, false);

document.getElementById("animation_pause").addEventListener("click", function() {
animation.pause();
}, false);
В нашем примере мы прикрепляем анимацию к переменной animation, как это ни странно. Затем мы прикрепляем 2 слушателя событий к элементам с id animation_start и animation_pause. Эти слушатели позаботятся о выполнении определенных функций при клике. Play запускает анимацию, pause уже понятно, что делает, а reverse немедленно перенесет вас к последнему ключевому кадру и полностью остановит анимацию.

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

Animation.addEventListener("finish", function() {
alert("The animation has ended.");
}, false);
В вышеприведенном примере мы просто запускаем сообщение о том, что анимация завершена.

Браузерная поддержка

animate() сейчас находится на ранней стадии разработки и сейчас обременена ярлыком «experimental». Поддержка этого параметра появится в Chrome, начиная с 36 версии. Если вы хотите опробовать ее сейчас, то можете скачать и установить Chrome Canary.

Небольшая библиотека для создания анимации на основе JavaScript. С её помощью можно анимировать свойства CSS, SVG-изображения или атрибуты DOM-дерева на веб-странице. Библиотека позволяет контролировать все аспекты анимации и предоставляет много способов для обозначения элементов, которые нужно привести в движение.

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

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

Примечание Если вы совсем новичок в JavaScript, предлагаем вам ознакомиться с по этому языку программирования.

Установка библиотеки

Для установки можно использовать команды npm или bower:

Npm install animejs bower install animejs

Вы также можете загрузить библиотеку и включить в свой проект или ссылаться на её последнюю версию через CDN.

После успешной установки вы сможете использовать Anime.js для добавления интересных анимаций к вашим элементам. Давайте начнём с базовых возможностей библиотеки.

Определение целевых элементов

Для создания анимации с помощью Anime.js нужно вызвать функцию anime() и передать ей объект с парами ключ-значение, которые определяют целевые элементы и свойства, которые вы хотите анимировать. Вы можете использовать ключевое слово targets , чтобы дать библиотеке понять, что вам нужно анимировать. Это ключевое слово может принимать значение в разных форматах.

CSS-селекторы : вы можете передавать один или более селекторов в виде значений для ключевого слова targets .

Var blue = anime({ targets: ".blue", translateY: 200 }); var redBlue = anime({ targets: ".red, .blue", translateY: 200 }); var even = anime({ targets: ".square:nth-child(even)", translateY: 200 }); var notRed = anime({ targets: ".square:not(.red)", translateY: 200 });

В первом случае Anime.js будет анимировать все элементы с классом blue . Во втором - blue или red . В третьем случае Anime.js будет анимировать все дочерние чётные элементы с классом square . А в последнем случае библиотека будет взаимодействовать со всеми элементами с классом square , у которых нет класса red .

DOM-узлы (DOM node) или коллекция узлов (NodeList): вы можете также использовать DOM-узел или NodeList в качестве значения для ключевого слова targets . Посмотрите на пример использования DOM-узла для targets .

Var special = anime({ targets: document.getElementById("special"), translateY: 200 }); var blue = anime({ targets: document.querySelector(".blue"), translateY: 200 }); var redBlue = anime({ targets: document.querySelectorAll(".red, .blue"), translateY: 200 }); var even = anime({ targets: document.querySelectorAll(".square:nth-child(even)"), translateY: 200 }); var notRed = anime({ targets: document.querySelectorAll(".square:not(.red)"), translateY: 200 });

В первом случае использовалась функция getElementById() , чтобы обратиться к определённому элементу. Функция querySelector() использовалась для обращения к элементу с классом blue . А функция querySelectorAll() применялась для обращения ко всем элементам внутри документа, которые соответствуют группе определённых селекторов или же, наоборот, не входят в неё.

Существует множество функций, которые вы также можете использовать для выбора целевого элемента. Например, вы можете обратиться к элементам с определённым классом, используя функцию getElementsByClassName() . Или к элементам с определённым тегом, используя функцию getElementsByTagName() .

Любая функция, возвращающая DOM-узел или NodeList, может использоваться для установки значения targets в Anime.js.

Объект: вы можете использовать объекты JavaScript в качестве значения для targets . Ключ этого объекта используется в качестве идентификатора, а значение - в качестве числа, которое нужно анимировать.

Затем вы сможете показать анимацию внутри другого HTML-элемента с помощью дополнительного JavaScript-кода. Ниже приведён пример анимации значений двух разных ключей одного объекта.

Var filesScanned = { count: 0, infected: 0 }; var scanning = anime({ targets: filesScanned, count: 1000, infected: 8, round: 1, update: function() { var scanCount = document.querySelector(".scan-count"); scanCount.innerHTML = filesScanned.count; var infectedCount = document.querySelector(".infected-count"); infectedCount.innerHTML = filesScanned.infected; } });

Код выше будет приводить в движение счётчик сканированных файлов от 0 до 1 000 и счётчик заражённых файлов от 0 до 8. Помните, что вы можете анимировать числовые значения только таким образом. При попытке анимировать ключ из AAA в BOY будет выведено сообщение об ошибке.

Кроме того, в коде использовалась функция обратного вызова ключа update , который вызывается на каждый кадр во время выполнения анимации. Здесь она использовалась для обновления количества сканированных и заражённых файлов. Однако вы можете пойти дальше и показать пользователям сообщение об ошибке, когда количество заражённых файлов превысит определённый порог.

Массив: возможность указывать массив JavaScript в качестве значения targets будет полезна, если вам нужно анимировать множество элементов, которые относятся к разным категориям. Например, если вы хотите анимировать DOM-узел, объект и множество других элементов, основанных на CSS-селекторах, то можно это сделать, поместив их в массив, а затем определить массив в качестве значения для targets . Пример ниже должен прояснить ситуацию.

Var multipleAnimations = anime({ targets: , translateY: 250 });

Какие свойства можно анимировать с помощью Anime.js

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

Свойства CSS

К таким, например, относятся ширина, высота и цвет для разных целевых элементов. Финальные значения разных анимируемых свойств вроде background-color определяются с использованием lowerCamelCase. Таким образом background-color превращается в backgroundColor . Код ниже иллюстрирует анимацию положения объекта left и цвета фона (backgroundColor) целевого объекта.

Var animateLeft = anime({ targets: ".square", left: "50%" }); var animateBackground = anime({ targets: ".square", backgroundColor: "#f96" });

Свойства могут принимать разные виды значений, которые они бы приняли при использовании обычного CSS. Например, свойство left может иметь такие значения: 50vh , 500px или 25em . Вы также можете не указывать единицу измерения после числа, но в таком случае ею станет px по умолчанию. Аналогичные действия можно выполнить с background-color , указав цвет в виде шестнадцатеричного значения или при помощи кода RGB или HSL.

CSS-трансформирование

Преобразование по осям X и Y достигается с помощью свойств translateX и translateY . Аналогичным образом можно масштабировать, наклонять или вращать элемент вдоль определённой оси, используя свойства: scale (масштабирование), skew (наклон) или rotate (поворот), соответствующие этой конкретной оси.

Существует возможность определения разных углов или в градусах, или с помощью свойства turn . Значение turn, равное 1, соответствует 360 градусам. Это позволяет сделать вычисления проще, так как вы знаете, на сколько нужно повернуть элементы относительно своей оси. В примере ниже показано, как происходит анимация масштабирования, перехода или поворота как единичного свойства, так и всех сразу.

Var animateScaling = anime({ targets: ".square", scale: 0.8 }); var animateTranslation = anime({ targets: ".square", translateX: window.innerWidth*0.8 }); var animateRotation = anime({ targets: ".square", rotate: "1turn" }); var animateAll = anime({ targets: ".square", scale: 0.8, translateX: window.innerWidth*0.8, rotate: "1turn" });

Атрибуты SVG

Единственное условие заключается в том, что значение атрибутов должно быть числовым. Способность анимировать разные атрибуты открывает возможности для создания некоторых классных эффектов. Поскольку эта статья ознакомительная, в ней будут приведены простые примеры.

И мы с пути кривого ни разу не свернем, а надо будет снова пойдет кривым путем - х/ф Айболит 66.

Существует великое множество готовы решений, позволяющих работать с перемещением по Кривыми Безье. В большинстве случаев практического применения готовых решений будет предостаточно. Но самостоятельная имплементация очень полезна для саморазвития, поэтому когда мне понадобилось в одном из проектов создать такую анимацию, я пошел в обход.

В данной статье я лишь описываю поток своего сознания, а не обучающий материал. Я не могу гарантировать, что конечные расчеты являются самыми оптимальными, но они работают - а это главное.

Итак

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

Кривая Безье названа в честь французского инженера Пьера Безье, который является одним из ее авторов. Кубическая кривая Безье - параметрическая кривая, задаваемая выражением (), состоит из 4 пар значений, где каждая пара - это x и y координаты точек, по которым образуется кривая.

Таким образом, кривая Безье состоит из двух точек и хотя бы одного вектора. Длинна вектора указывает насколько нужно подтягивать линию изгиба в его направлении. В идеальном случае у одной кривой имеется два вектора, у начальной и у конечной точки:

Как и в случае рисования кривой, так и в случае движения по кривой участвует одна и та же формула, которую можно найти на Википедии :

Для произведения расчетов нужно значение прогресса движения (t), (т.е. разбиваем условную анимацию на любое количество кадров, которое нам будет удобно, или использует относительное значение каждого кадра).

Делаем имплементацию

Предположим, мы планируем дойти от точки до точки двухсегметной кривой за четыре секунды с частотой кадров 12 fps. Тогда д елим секунду на 12 и получаем отрезок времени, которую принимаем за единицу анимации (фрейм).

Var frameDuration = 1000/12;

Теперь зная время, за которое мы хотим пройти кривую и количество кадров, мы можем получить полное количество кадров, входящих во всю анимацию. Для этого делим 4 секунды на количества кадров в секунду.

// Общее_время_в_мс / (1000_миллисекунд/количество_кадров)
var framesCount = 4000/frameDuration;

Зная общее количество кадров, мы, используя курсор текущего кадра, можем получить значение прогресса анимации t, просто поделив текущий кадр на общее количество кадров анимации;

Var t = currentFrame/framesCount;

Таким образом, у нас е сть значение начальной точки - P0x, P0y; первой контрольной точки - P1x, P1y; второй контрольной точки - P2x, P2y; и завершающей точки - P3x,P3y, и значение прогресса анимации t . Остается подставить всё это в формулу

и мы получаем нужные нам координаты объекта в любой момент времени (t).

X = (Math.pow((1 - t), 3) * P0x) +
(3 * Math.pow((1 - t), 2) * t * P1x) +
(3* (1 - t) * Math.pow(t, 2) * P2x) +
(Math.pow(t, 3) * P3x) y = (Math.pow((1 - t), 3) * P0y) +
(3 * Math.pow((1 - t), 2) * t * P1y) +
(3* (1 - t) * Math.pow(t, 2) * P2y) +
(Math.pow(t, 3) * P3y)

Поворот к вектору движения

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

Что бы узнать угол вектора, нам нужно найти угол, который образуют две ближайших точки на кривой, по отношении к друг другу. Т.е. мы берем координаты текущего положения объекта, и координаты положения объекта в предыдущем фрейме. Назовем их x0,y0 и x,y .

Фактически x0-x, y0-y -  это две стороны треугольника, зная которые мы можем найти угол по формуле решения треугольника по двум сторонам и прямому углу между ними.

c=sqrt(a2 + b2) A=arccos((b2+c2-a2)/2bc)

Но только вот какая незадача: угол вектора может варьироваться от 0 до 360, а угол в треугольнике у нас от 0 до 179,9. Нам нужно найти угол между двумя векторами:

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

    Когда направляющая смотрит снизу вверх, слева направо, искомый угол нашего воображаемого треугольника находит внизу слева. В таком случае стороной a становится разница между x и x0 , а b разница между y и y0 . Результативный угол мы получаем через сумму квадратов всех сторон, деленных на двойную сумму катета и гипотенузы.

    A=arccos((b2+c2-a2)/2bc)

    Но когда вектор смотрит слева на право, сверху вниз, наши стороны треугольника меняются местами. В этом случае стороной a становится разница между y и y0 , а b x и x0 соответственно. Т.е. всё наоборот от предыдущего случая. Но решение остается таким же.

    Всё бы ничего, но когда направляющая начинает движение сверху вниз, слева на право, предыдущая схема перестает работать. Во-первых мы снова меняем стороны местами, а искомый угол становится противоположным. И находим его уже по вспомогательной формуле 90-$A, кроме того прибавляем 90, что бы наш объект смотрел в правильном направлении.

    В четвертом же случае, когда направляющая смотрит снизу вверх, справа налево, мы опять ищем угол $B, но на этот раз прибавляем к его значению 180 градусов.

    Плюс ко всему нужно не забывать, что существует варианты нулевой длинны сторон, что приведет к ошибке расчетов. Поэтому важно не забыть проводить проверку одного из 4-х направлений движений, и кроме того проверку на нулевую длину сторон, при значениях угла 0, 90, 180 и 270.

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

    Парсинг Svg

    Осталось сделать так, что бы скрипт, создающий анимацию, мог принимать в качестве траектории сразу SVG путь . Мне не удалось найти ни одного качественного конвертера SVG-PATH в CUBIC-BEZIER POINTS, поэтому написал собственную реализацию парсинга SVG пути в javascript-читабельный формат.

    В этот процесс я не стану углубляться, скажу лишь, что английская литера M в устанавливает начало линии, далее команды s/S (smooth curveto) или c/C (curvet) позволяют создавать контрольные точки, причем значения могут быть как абсолютными, так и относительными. И хотя в SVG PATH типов команд достаточно много (M, L, H, V, C, S, Q, T, A, Z), я изучил и создал парсер только для 3-х из них. Результатом 6 часовых стараний стала функция svgPathToCubicBezierPoints , которая конвертит путь SVG в в массив точек в процентном эквиваленте.

    Заключение

    Вот, пожалуй и все. Если вам просто необходимо создать анимацию, основанную на движениях на кривым Безье, то не стоит изобретать велосипед, а стоит воспользоваться существующими библиотеками, такими как Raphael или .

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