Вступление и краткий обзор SMIL анимаций, за и против
Данная статья является единственным туториалом по созданию анимаций для SVG изображений на SMIL, который тебе понадобится для создания клёвых и анимированных превьюшек и иконок для своего сайта. Для данного туториала я создал специальный инструмент - редактор анимаций на SMIL для SVG изображений. Который позволит тебе отработать различные техники и навыки в создании анимаций.
Я решил написать данную статью, потому что считаю, что могу сделать лучше и нагляднее чем существующие аналоги в интернете. А так же потому что, всё за раз я запомнить не смогу и скорее всего забуду, а постоянно рыться в документации и прыгать от главы к главе, тоже не хочется.
Поэтому данный гайд, будет поделён на главы, и чем глубже тем сложнее. То есть, если ты только начал, то лучше всего начать с первой главы (или со второй, если считать эту главу за первую). Ну а если ты уже прошаренный аниматор, то лучше ориентироваться по проблеме с которой столкнулся и начать читать с соответствующей главы.
Собственно говоря, почему именно стоит использовать SMIL анимации, вместо CSS или JS? У данного подхода есть много преимуществ и всего два недостатка. Вот основные преимущества:
Лёгкая встраиваемость. То есть не нужно добавлять дополнительных файлов или зависимостей. Просто отредактируй уже существующий или используемый SVG изображение и всё готово.
Гибкость. Только на этом языке можно описать очень сложные анимации, где даже JS не в силах помочь
Морфинг форм путей анимаций. Об этом подробнее в соответствующей главе, но если кратко, то позволяет очень лего пустить элемент по любому, даже самому извилистому, пути.
Встроенный функционал для синхронизации анимаций.
Просто быстрее, ибо всё, и само анимируемое изображение, и код анимации в одном файле.
Широкая поддержка браузерами. Хотя не полная, так Opera и IE не поддерживают SVG анимации совсем. Но по статистике с https://caniuse.com/?search=smil, большинство пользователей сможет оценить ваши труды
Статистика поддержки SMIL браузерами
Теперь давай про недостатки:
Это довольно сложный язык для создания анимаций. Потребуется время для оттачивания мастерства в его использовании
Не полная поддержка. Да, я записал его и к плюсам и к минусам. Потому что для меня, если я вижу 96% поддержки среди пользовательских браузеров, значит это хорошо. Но для прожжённых веб-разработчиков этого может быть не достаточно и им нужна полная поддержка от всех существующих браузеров.
set - просто устанавливает значение для указанного элемента
animateMotion - для перемещения и трансформирования элемента. Больше об этом элементе в этой главе.
animateTransform - для изменения геометрии элемента. Сдвиг, растяжение, вращение, размеры. Больше о нём в этой главе
И существует всего два способа расположить эти элементы:
Внутри целевого элемента, без указания ссылки на него
Вне целевого элемента, с указанием ссылки на него используя href атрибут.
В первом случае, мы располагаем любой элемент анимации в том объекте, к которому хотим применить анимацию, например:
То есть мы зададим белый цвет всем элементам в группе с id="20". Очевидно, что для относительно простых изображений, такой способ более чем приемлем. Но как только число элементов перевалит за сотню и выше, потребуется как-то организовывать код для анимаций.
Для этого можно поместить все элементы анимации в одно место, где и заниматься их редактированием и группировкой. Нужно только указать ID в атрибут href, того элемента, который хотим анимировать, например:
Данный способ и использует мой инструмент. Он помещает все анимации в одно место, а пользователю нужно только указать ID требуемых для анимации элементов.
Простая анимация
Начнём пожалуй с самых простых анимаций. Анимаций передвижения объектов по холсту.
В примере кода выше я использовал минимально необходимые атрибуты для анимации:
href - Это ссылка на объект, который мы хотим анимировать
attributeName - То, какой атрибут мы хотим анимировать
to - К какому значению необходимо привести данный объект в конце анимации
dur - как долго эта анимация должна работать
repeatCount - Вот это свойство необязательно, но я хотел, чтобы, ты, мой читатель точно увидел работающую анимацию. Значение этого атрибута - indefinite, говорит о том, что анимация будет повторяться бесконечно.
Можно поиграться с перемещением ещё. Ведь можно указать с какого значения начинать(from) и на сколько менять это значение(by).
Вот так вот можно создать эффект бесконечного движения объекта. Важно так же понимать, что используя атрибут from, с начала анимации объект будет помещён туда без интерполяции, то есть мгновенно, что может быть не желательно для некоторых анимаций.
Ещё более простые анимации
Кроме элемента animate, можно использовать ещё и set. Он очень прост в своём использовании и не анимирует вообще, а только задаёт значения для целевого объекта. Вот наглядный пример:
В этом примере, чтобы анимация работала постоянно я не использовал временные значения, а вместо их евент окончания предыдущей анимации (в данном случае не анимации, но установки значения, которое происходит мгновенно). Об этих эвентах подробнее будет рассказано в этой главе.
Перемещаем объекты
В предыдущей главе мы пробовали перемещение объектов используя общий элемент анимации - animate. И обычный сеттер значений - set. А так как перемещение объектов, это самый распространённый тип анимации, SMIL, представил отдельный элемент анимации для перемещения объектов - animateMotion.
Вот как можно его использовать:
Сначала я задал изначальную точку для начала анимации при помощи set. После создал четыре анимации передвижения слева-направо, сверху-вниз, справа-налево, снизу-вверх. Объединил все эти анимации используя события окончания каждой анимации и что главное, использовал новые атрибуты такие как fill и additive.
Атрибут fill - задаёт поведение для изменения конечного состояния анимируемых атрибутов. Так без fill="freeze" значения атрибутов x и y не изменятся и вернутся к состоянию до начала анимации.
Атрибут additive - позволяет суммировать результат предыдущей анимации её текущим изменением.
Это всё классно, но на самом деле animateMotion придумывался с уклоном использования вместе с атрибутом path, который способен задавать кривые маршрутов перемещения объектов. Например, так:
Есть ещё один способ задания маршрута движения объекта. Создаём элемент path и сохраняем его. После чего обращаемся к нему через mpath, обёрнутый вокруг animateMotion. Код ниже аналогичен коду выше.
Собственно говоря, если нужно анимировать путь объекта, а этот путь очень сложен и тернист, то открываем свой любимый SVG редактор (в моём случае это InkScape), рисуем этот путь и копируем его path. Вот так:
После чего вставляем скопированный путь в path атрибут. О том, как устроен данный атрибут и как его использовать, можно узнать в этой, исчерпывающей документации. Или можно прочитать более упрощённую версию в контексте использования SMIL.
Анимируем цвета
Теперь немного о цветах. Точнее об их анимации. Как было замечено раньше, чтобы анимировать цвета можно использовать как animate, так и animateColor элементы. Но использовать лучше animate.
Первый квадрат, который вверху слева, анимируется от текущего цвета до целевого.
Второй, который вверху справа, анимирует цвет от #fff до #111. Игнорируя изначальный цвет заполнения.
Третий, который внизу слева, анимирует цвета пошагово в указанном списке в атрибуте values.
И четвёртый квадрат анимирует на заполнение - атрибут fill, но границу квадрата - атрибут stroke.
Правила анимации к ним применяются те же, что и к обычным анимациям перемещения и трансформациям. Кстати о трансформациях, о них дальше.
Изменяем формы и объекты
Это одна из тех особенностей анимирования SVG изображений, ради которой и стоит учить данный язык для анимирования. Хотя бы потому что, это так просто сделать. Например, вот так:
Я согласен, очень много кода для такого простого морфинга форм, но что тут важно уяснить. Вся эта анимация возможна благодаря атрибуту values, который пошагово говорит, какие узлы и куда эти узлы поместить. Каждый шаг разделяется точкой с запятой.
Причём довольно важно учитывать тот факт, что если хочется получить именно анимацию, а не резкий скачок к целевой точке, необходимо чтобы атрибут path имел идентичную структуру на каждом шаге. То есть если первый узел описывается вот такой вот структурой пути - "M L L L Z", то и второй узел должен состоять из такой же структуры.
Тут может возникнуть довольно резонный вопрос, а как и где мне получить необходимые позиции узлов? Я эти позиции сам не вычисляю, а копирую из обычного редактора SVG - InkScape. Вот так:
В твоём редакторе может быть чуть-чуть по другому, но в InkScape всё довольно прямолинейно и понятно.
Трансформации объектов
Если такая детальная трансформация путей не нужна, или нужно трансформировать например rect элемент, на помощь придёт такой элемент анимации как animateTransform. Он позволяет анимировать базовые трансформации как scale, rotate и translate.
Вот примеры анимаций для трансформаций объектов:
Заметь, что я использую атрибут values, чтобы пошагово задать необходимые углы поворотов и степени масштабирования объекта. Так просто нагляднее для читателя, увидеть в действии ту или иную анимацию.
Сглаживаем анимации
Иногда движения могут показаться слишком резкими или "прямолинейными". И тебе это не кажется, ведь по умолчанию, все анимируемые атрибуты изменяют свои свойства прямолинейно. Чтобы это изменить нужно прибегнуть к таким атрибутам анимирования как calcMode и keySplines.
Нужно задать calcMode равным spline. А в атрибут keySplines придётся записать 4 числа описывающих кривую сплайна. Вместе они задают скорость изменения анимируемых атрибутов при помощи сплайнов.
Вообще calcMode довольно интересный атрибут, который может в корне изменить стиль и поведение анимации. Я, конечно же, мог бы попытаться описать работу данного атрибута, но наверное лучше оставить это тем, кто SMIL и придумал и просто направить тебя в официальную документацию для дальнейшего ознакомления.
Мне было лень делать дополнительный инструмент для генерирования таких сплайнов, может когда-нибудь и сделаю, но а пока можно использовать вот такой вот сайт, специально предназначенный для генерации кастомных сплайнов. Больше деталей о том, как это работает, читай в официальной документации.
Интерактивные анимации
Все мои анимации в этой статье начинаются сразу же после загрузки самого изображения в древо DOM. В коде это выглядит вот так: begin="0". И такое поведение является стандартным, то есть его не нужно прописывать самому, оно подразумевается.
Но иногда хочется чтобы анимация выполнялась по клику на конкретный элемент или при ховере мыши, например. Это легко реализовать используя в атрибуте begin не время, но имена событий, как я это уже делал в этой главе. Так например, сможешь ли ты открыть все анимации на данном изображении:
Чтобы запустить анимацию для первого квадрата, слева-вверху, нужно лишь навести мышь. На прямоугольник придётся кликнуть. Анимация для круга может быть активирована двумя путями. Первый это обычный клик, второй это после окончания анимации квадрата. Закруглённый треугольник активирует свою анимацию после того, как ты уберёшь мышь. Ну и наконец, анимация для пятиугольника будет активирована спустя 2 секунды после клика.
События нужно использовать в связке с конкретным элементом анимации. Где сначала идёт ИД элемента анимации, а потом, через точку, идёт обращение к событию.
Вот все, встроенные события, которые могут использоваться в begin и end атрибуте:
begin - когда анимация началась
end - когда анимация закончилась, то есть если ко-во повторов 5, то данное событие активируется только в конце 5-ого повтора
repeat - когда анимация повторилась, то есть если ко-во повторов 5, то в конце каждого повтора.
Заключение или что будет дальше
Вот и всё, что я знаю об анимациях SVG изображений через SMIL. Минимальный, но вполне достаточный инструментарий, чтобы сделать довольно классные анимации для своего сайта.
Так же как и с другими статьями такого типа, чем старше она будет, тем больше деталей эта статья соберёт, ведь и я стоять на месте не буду. И может ещё научусь парочке-другой приёмов связанных с анимациями. А так, надеюсь статья была тебе полезна и помогла в короткие сроки анимировать своё SVG-изображение.
В этой статье я разберу типы форматеров (formats) quilljs, и объясню некоторые нюансы работы с таблицами, шрифтами, изображениями и видео. Так же покажу как переопределить форматер(ql-formats) на примере ссылки