В последнее время набирают популярность анимационные эффекты рисования линий с чистого листа. Магические картинки анимации игровой консоли или дядьки в кресле копируются с сайта на сайт. Конечно это круто выглядит и наверняка у вас появилось желание сделать, что нибудь подобное для своего сайта. Для этого есть несколько плагинов реализации эффекта анимации линий. Но, я не буду перечислять их, объяснять как они работают, как плагины можно “заточить” под себя. При желании всё это можно найти.
Задача данной статьи иная – понять, как реализуется эффект анимации, отчего зависит направление, последовательность и продолжительность рисования линий.
Почему один файл SVG можно заставить отрисовываться, а другой нет.
Далее будет логично заняться более интересными вещами – последовательной и параллельной анимацией нескольких фрагментов изображения, реализацией плавного преобразования одной векторной картинки в другую.
Чтобы получить эффект анимации рисования линии с нуля до конца, нужно прописать в стилях анимируемого объекта для начальной точки:
- stroke-dasharray = getTotalLengtht
- stroke-dashoffset = getTotalLengtht
- добавить команду анимации для линии или пути
- для конечной точки линии выполнить условие – stroke-dashoffset = “0”
1 |
<animate attributeName="stroke-dashoffset" from="getTotalLengtht" to="0" dur="18s" repeatCount="indefinite" calcMode="paced"/> |
stroke-dasharray – атрибут, отвечающий за пунктирную линию. Например: stroke-dasharray: 10px 10px; Первая цифра – длина линии, вторая цифра – длина пробела. Если задана только одна цифра – stroke-dasharray: 10px, то длина и пробел будут равны. Я пользуюсь этим свойством, так как проще анимировать один параметр, чем два.
stroke-dashoffset – атрибут, отвечающий за отступ от начала линии или пути.
getTotalLengtht – команда, которая позволяет вычислить полную длину пути.
Из примера выше видно, что с начала анимации – from отступ равен полной длине пути, затем он уменьшается to=”0″ до нуля. В результате рисуется линия от нуля до конца, (полная длина).
Для простоты освоения этого метода найдите или сами напишите SVG файл, где есть только один <path>. Присвойте ему уникальный идентификатор id=”..”
Следующий шаг – нужно измерить длину path в вашем файле, который вы хотите анимировать. Для этого я подготовил Html файл, в который вы можете скопировать на место существующего пути, патч из своего файла SVG, затем нажав на кнопку “Total” узнать длину пути, которую необходимо подставить в атрибуты строки патча: stroke-dasharray = “70” и stroke-dashoffset = “70” Ниже код этого Html файла.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<!DOCTYPE html> <head> <title> Измерение длины пути</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <input type="button" value="Total" onclick="TotalLength()"/> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events" width="100%" height="100%" > <path id="check" fill= "none" stroke ="green" stroke-width ="1" d="M 34.6 14.6 L 21 28.2 L 15.4 22.6 L 12.6 25.4 L 21 33.8 L 37.4 17.4z" /> </svg> <script> function TotalLength(){ var path = document.querySelector('#check'); var len = Math.round(path.getTotalLength() ); alert("Длина пути - " + len); }; </script> </html> |
Следующий шаг – добавление анимации в SVG файл для плавного уменьшения параметра атрибута stroke-dashoffset с максимального значения до нуля. Обратите внимание, что при вложениии анимации в одиночный тег <path …/> его нужно преобразовать в двойной. <path …> </path> Подробнее здесь.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 126 126" > <title>animation logo picasa</title> <path id="check" fill="none" stroke ="black" stroke-dasharray= "600" stroke-dashoffset="600" d="M113.5 57.7l-8.5-11.4 ... 86.3 72.8z"> <animate id="p1" attributeName="stroke-dashoffset" begin="svg1.click" values="600; 0" dur="10s" repeatCount="1" fill="freeze" calcMode="linear"/> </path> <text x="98" y="17" font-size="11" font-family="Ariel" text-anchor="middle" fill="green" stroke="grey" stroke-width="0.5px" >Click me</text> </svg> |
Для лучшего понимания я освободил код от лишних подробностей. Полную рабочую версию можете забрать по кнопке.
В команде анимации значения параметра, в нашем случае это изменение – stroke-dashoffset можно указывать по разному, как from=”600″ to=”0″,
так и другим способом – values=”600;0″
Последний способ более удобен, так как можно указать больше двух значений, например: values=”600; 0; 600″
Это понадобится для реализации двойного эффекта рисования линий: сначала появление изображения, затем его плавное исчезновение.
begin=”svg1.click” – начало анимации по клику мышки на любом месте SVG полотна, так как ему присвоен идентификатор – <svg id=”svg1″ см. 1 строку кода выше.
fill=”freeze” – изображение “замораживается” после окончания анимации.
calcMode=”linear” – задается равномерность анимации, то есть скорость зависит только от заданного времени продолжительности анимации dur=”10s” и длины пути.
Идея проста в реализации. Если мы научились анимировать рисование линии с нуля до полной длины, то можно повернуть процесс и в обратную сторону. Заставить линию плавно уменьшать длину от максимума до нуля. Для этого нужно, чтобы
stroke-dashoffset изменялся от нуля до полной длины линии values=”0;700″, тем самым скрывая её полностью. В нашем примере совмещены две последовательные анимации – рисование линий от нулевой длины до максимальной и от максимальной длины до нулевой. Соответственно анимация атрибута stroke-dashoffset должна быть зеркальной – values=”700;0;700″ Ниже пример кода анимации.
1 2 3 4 5 6 7 8 9 10 11 |
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 126 126" > <path class="path" fill="none" stroke ="black" stroke-dasharray= "700" stroke-dashoffset="0" d="M113.5 56.2l-8.5-11.4 ......... 59.4z"> <animate id="p1" attributeName="stroke-dashoffset" begin="svg1.click" repeatCount="1" values="700;0;700;" dur="10s" fill="freeze" calcMode="linear" restart="whenNotActive"/> </path> </svg> |
Все параметры анимации нам уже знакомы, добавился один новый:
restart=”whenNotActive” – запрет начала новой анимации, пока не закончится уже запущенная. В нашем случае пока не закончится весь процесс рисования линий туда-сюда, новую анимацию линий кликаньем мышки не запустить.
Вы наверное заметили наличие паузы после окончания первого этапа анимации – рисование линии, до начала второго этапа – уменьшение длины линий. Паузы не должно быть, судя по коду анимации, но она есть. Почему так происходит?
1 2 3 4 5 6 7 |
<path class="path" fill="none" stroke ="black" stroke-dasharray= "700" stroke-dashoffset="0" d="M113.5 56.2l20..... 113.5 56.2z M63.1 100.5c-20.6 ..... 100.5 63.1 100.5z M63.1 29.3c-18.7.....29.3 63.1 29.3z M54.1 39.6l0 8.1.....7.9 0L54.1 39.6z M74.4 87.9c0 .....74.4 87.9 74.4 87.9z M72.9 59.4c.....4.7 59.4 72.9 59.4z" /> |
Потому-что в SVG файле векторное изображение рисуется не одним пером, а несколькими по количеству равным количеству подпутей, каждый из которых начинается командой “M” или “m” – moveto – переместить перо в точку. Пример кода смотри выше.
Параллельно рисовать несколькими перьями быстрее, чем одним, но именно продолжительность рисования одним пером всего пути path интерпретатор SVG берет в расчет. Поэтому разница по времени параллельного рисования несколькими перьями и одним пером уходит в паузу. Всё уже нарисовано, а интерпретатор ждёт, пока одно перо виртуально дорисует всё до конца.
Для доказательства возьму SVG файл олененка нарисованный одним патчем. Подпуть тоже один – одна команда “M” в <path. Значит рисование будет одним пером. Продолжительность анимации я установил в 20 секунд. Паузы между анимациями нет. Ровно по 10 секунд на рисование и исчезновение линии! Оцените плавность хода. Найти подобный файл можно среди SVG иконок. Очистить файл от всего лишнего вам поможет редактор Svg-Editor от Peter Collingridge. Как им пользоваться написано здесь. Скачать файл олененка можно по кнопке.
Пишу на тот случай, если вы всё делали, как написано в статье, но не достигли результата. Прежде всего не сдавайтесь. Тщательно всё проверьте. Может дело в ерунде, например забыли нужную точку с запятой, кавычку в коде. Сообщения об ошибке не будет, но и анимация работать не будет.
Таковы особенности работы интерпретатора xml. Он реагирует не на все ошибки. На незакрытый тег, выдает сообщение об ошибке, но неправильное написание названий аргументов или их значений параметров проигнорирует.
Ещё раз проверьте:
- Добавление аргументов строки патча – stroke-dasharray=”953″ и stroke-dashoffset=”953″, где параметр – “953” это полная, измеренная длина патча (линии)
- при вложениии тега анимации в одиночный тег <path …/>, его нужно преобразовать в двойной – <path …> </path>
- Как вы будете запускать анимацию? Если щелчком по месту расположения картинки – begin=”svg1.click”, то необходимо указать уникальный идентификатор – <svg id=”svg1″ полотна SVG. Если с интервалом от загрузки картинки, то в теге анимации необходимо указать – begin=”2s” интервал.
- Проверьте правильность вложения SVG файла в вашу HTML страничку. Лучше сделать это либо посредством <object> тега, либо инлайн. Подробнее здесь.
⇚ Анимация многоугольников
Анимация иконки – разбитое сердце ⇛
А как сделать что бы анимация срабатывала когда прокрутим к нужному блоку ?