Сегодня мы с вами разомнем наши пальчики и немного поработаем с SVG. Почему? Да потому что с ним легко работать человеку, который "собаку съел" в верстке. SVG - это векторный формат, основанный на XML. То есть у SVG-рисунка есть своя DOM, к различным элементам можно применять CSS-правила и управлять старым добрым JavaScript'ом.
Рисуем и анимируем круг
Создадим наш круг с помощью тега <circle />
и поместим внутрь него тег <animate />
, отвечающий за анимацию:
<circle>
<animate />
</circle>
Напомню, что тег <circle />
имеет параметры:
- cx, cy
- координаты по оси X и Y. Координаты отсчитываются с верхнего левого угла (это 0-0)
- r
- радиус
- fill
- цвет заливки
- style
- стиль элемента
- stroke
- цвет границы
- stroke-width
- ширина границы
Наш круг выглядит следующим образом (параметры анимации мы с вами будем писать постепенно с моими подробными комментариями):
<circle fill="#FFFFFF" stroke="#B450FF" stroke-width="6" stroke-miterlimit="10" cx="153" cy="127" r="6">
<animate
Параметр attributeName определяет атрибут, который будет участвовать в анимации. Это может быть прозрачность, ширина границы, ширина, или ряд других атрибутов. Мы решили использовать су, который определяет положение центра круга относительно полотна по оси Y:
attributeName="cy"
Свойства from и to указывают нашей фигуре координаты в начале и в конце анимации (т.е. для атрибута, к которому применяется анимация). Мне нужно, чтобы наша анимация работала циклически и плавно, поэтому свойства from и to содержат идентичные значения. Обратите внимание: они равны значению cy моего элемента-кружка.
from="127" to="127"
Мы можем задать начальную задержку для анимации с помощью свойства begin. Поскольку анимация должна воспроизводиться сразу же, установим его значение равнум 0. Общая продолжительность анимации определяется свойством dur.
begin="0s" dur="4s"
Данные значения относятся к атрибуту, к которому будет применена анимация. Так как выше для attributeName мы прописали cy, данные значения определяют координаты cy. Это 3 точки, в которые будет перемещен наш кружок во время анимации (127, 117 и 90 единиц). Мы повторяем эти значения, таким образом в движении кружка образуется пауза (хотя на самом деле это просто возврат в прежнюю точку). Седьмое значение завершает последнюю паузу и заканчивает наш цикл.
values="127;117;117;90;90;127;127"
Обратите внимание, что последние значения идентичны первому значению, также эти значения идентичны значениям from и to.
Использование дублирующихся значений является одним из методов вставки пауз в анимацию. Другой, возможно более подходящий для этого метод заключается в создании отдельных анимационных элементов для каждого из движений, затем в последовательном их вызове с помощью id, атрибута end и значения offset. Я выбрал первый вариант, использующий дублирующиеся значения, для того, чтобы уменьшить количество элементов в моем SVG изображении.
Настройка анимации
Атрибут keySplines позволяет замедлять и ускорять анимацию. Значением атрибута является список координат контрольных точек кривой Безье, разделенный точкой с запятой. Каждое описание кривой представляет собой набор из четырех значений с плавающей точкой: x1 y1 x2 y2, разделенных пробелом, описывающих контрольные точки Безье в течение одного временного сегмента. Два соответствующих значения атрибута KeyTimes определяют опорные точки этой кривой. Таким образом, в атрибуте keySplines наборов контрольных точек будет на один меньше, чем значений в KeyTimes. Значения должны быть в диапазоне от 0 до 1.
keySplines="
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1"
Четыре значения на каждой строке - это координаты опорных точек построения кривых изинга. Давайте сделаем визуальное отображение этого с помощью векторного рисунка:
Без метода easing (смягчение) наша анимация выглядела бы механической. Благодаря этому методу мы можем добавить в нее динамику, так сказать, "вдохнуть в нее жизнь"
Спецификации на атрибут keySplines требуют, чтобы эти значения лежали в пределах от 0 до 1. В начале мы получили эффект отскока (ниже) (со значениями 0.4 1.6 0.8 0.8), но при этом одно из значений находилось вне требуемого диапазона. Хотя это прекрасно работает на движке Webkit, в Firefox анимация ломается. (Выброс кривой и ее окончание (в результирующей кривой Безье) определяют отскок кружка.)
Так как мы имеем 6 движений (transitions) - три раза кружок перемещается в новое положение, и три раза он возвращается в исходное положение (пауза) - то в атрибут keySplines мы прописываем 6 строчек, разделенных точкой с запятой. Вы можете использовать свои значения для каждого перехода (transition)
Кадры (frames)
Параметр keyTimes задает темп появления ключевых кадров (keyframes)
keyTimes="0;0.22;0.33;0.55;0.66;0.88;1"
Данные временные показатели согласованы с нашими значениями. Я решил сделать время движения в два раза большим времени пауз, поэтому для движения я выделил примерно 0.22 единиц и для пауз около 0.11 единиц. Соединив все эти значения вместе, мы можем отобразить результат следующим образом:
С ровным темпом время движения равно времени пауз. Меняя данный темп, я корректирую время остановки и движения и увеличиваю время движения. Более короткие остановки добавляют резкость в нужные нам места
Атрибут calcMode указывает, каким образом осуществляется переход между значениями. Значение spline обращается к методу изинга по кубической кривой Безье (cubic Bezier easing method), о котором мы упоминали выше.
calcMode="spline"
Для атрибута repeatCount мы выбрали значение indefinite, таким образом наша анимация повторяется циклически. В заключение мы закрываем наши теги animate
и circle
.
repeatCount="indefinite"
/>
</circle>
Итак, в итоге у нас получился следующий код:
<circle fill="#FFFFFF" stroke="#B450FF" stroke-width="6" stroke-miterlimit="10" cx="153" cy="127" r="6">
<animate
attributeName="cy"
from="127"
to="127"
begin="0s"
dur="4s"
values="127;117;117;90;90;127;127"
keySplines="
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1;
0.1 0.8 0.2 1"
keyTimes="0;0.22;0.33;0.55;0.66;0.88;1"
calcMode="spline"
repeatCount="indefinite"
/>
</circle>
Все элементы нашего изображения используют рассмотренный нами метод. Данная технология таким же образом применена и к линиям. В случае кружков мы применяем анимацию к точке cy. Для каждой же линии мы делаем анимацию точек y1 и y2 (два отдельных элемента animate
).
Мы предпочли использовать формат SVG вместо встроенного видео или GIF анимации в целях снижения веса страницы и времени загрузки. Наше конечное изображение весит всего лишь 15 kb. Для анимации изображений в формате SVG можно использовать библиотеки JavaScript, но мы отказались от такого метода в силу невозможности создать такой же легкий и быстрый код, какой мы получили, работая с чистым форматом SVG.
Итак, мы подробно разобрали анимацию изображения в формате SVG и получили некоторое представление о том, как она работает. Удачи!