Домой / Спам / Графическая анимация SVG. Руководство по анимации SVG (SMIL) В чем делаются анимированные svg

Графическая анимация SVG. Руководство по анимации SVG (SMIL) В чем делаются анимированные svg

5 января 2014 в 16:27

Анимация SVG-элемента path

  • Разработка веб-сайтов ,
  • Визуализация данных
  • Tutorial

Думаю многие видели обзоры игровых консолей нового поколения от Polygon (Vox Media) . Это те, где консоли отрисовывались в стиле blueprint"ов:

Обзоры выглядели круто, довольно необычно и ново. О том как реализована основная фишка обзоров - SVG анимация, как сделать нечто подобное самому, и какие ещё «секретные» возможности скрывает старый добрый SVG в плане анимации элемента path - можно узнать под катом.

Stroke-dasharray interpolation, теория

Вообще техника подобной анимации линий не нова, просто до недавнего времени SVG и всё, что с ним связано, на мой взгляд, было несправедливо предано забвению, но к счастью ситуация меняется. Итак, трюк с анимацией элемента path возможен благодаря свойству stroke-dasharray элемента path . Это свойство позволяет задавать параметры пунктирной линии, а именно длину штриха и промежутка между штрихами. Если задать длину штриха равной всей длине линии, то получим обыкновенную сплошную линию. Если же задать длину штриха равной нулю, а длину промежутка опять-таки равной всей длине линии, то получим невидимую линию. А постепенно увеличивая длину штриха при длине промежутка, равной длине всей линии, мы можем имитировать её отрисовку. При таком подходе отрисовка будет происходить от начала линии. Если же вдруг необходимо отрисовывать с конца, то нужно использовать ещё одно свойство: stroke-dashoffset . Это свойство определяет смещение для первого штриха. Таким образом, уменьшая смещение и увеличивая длину штриха, получим отрисовку с конца линии.

Ребята из Vox Media использовали гибридный вариант (который, на мой взгляд, избыточен), кстати почитать о том, как они это делали, можно (и нужно) в их блоге: Polygon feature design: SVG animations for fun and profit .

Реализация SVG анимации

В Vox Media предлагают использовать requestAnimationFrame для плавности анимации, но у нас немного другие цели, так что мы пойдём более простым путём, воспользуемся библиотекой D3.js и реализованной в ней анимацией на основе длительности.

Вот собственно рабочий код, использовавшийся для анимации консоли из начала статьи.

Queue() .defer(d3.xml, "PS4.svg", "image/svg+xml") .await(ready); function ready(error, xml) { //Adding our svg file to HTML document var importedNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"), svgWidth = svg.attr("width"), svgHeight = svg.attr("height"); var paths = svg.selectAll("path") .call(transition); function transition(path) { path.transition() .duration(5000) .attrTween("stroke-dasharray", tweenDash) .each("end", function() { d3.select(this).call(transition); }); // infinite loop } function tweenDash() { var l = this.getTotalLength(), i = d3.interpolateString("0," + l, l + "," + l); // interpolation of stroke-dasharray attr return function(t) { return i(t); }; } }


Начнём просто с движения вдоль линии, пока без вращения.

Queue() .defer(d3.xml, "wiggle.svg", "image/svg+xml") .await(ready); function ready(error, xml) { //Adding our svg file to HTML document var importedNode = document.importNode(xml.documentElement, true); d3.select("#pathAnimation").node().appendChild(importedNode); var svg = d3.select("svg"); var path = svg.select("path#wiggle"), startPoint = pathStartPoint(path); var marker = svg.append("circle"); marker.attr("r", 7) .attr("transform", "translate(" + startPoint + ")"); transition(); //Get path start point for placing marker function pathStartPoint(path) { var d = path.attr("d"), dsplitted = d.split(" "); return dsplitted.split(","); } function transition() { marker.transition() .duration(7500) .attrTween("transform", translateAlong(path.node())) .each("end", transition);// infinite loop } function translateAlong(path) { var l = path.getTotalLength(); return function(i) { return function(t) { var p = path.getPointAtLength(t * l); return "translate(" + p.x + "," + p.y + ")";//Move marker } } } }
Здесь pathStartPoint(path) вытаскивает координаты начала линии из атрибута элемента path . В translateAlong(path) с помощью интерполятора задаются координаты нашего маркера. Пример можно посмотреть здесь: Marker animation along SVG path element with D3.js . А ещё можно объединить анимацию отрисовки линии и движение маркера, выглядеть это может следующим образом: Marker animation along SVG path element with D3.js II .

Усложним задачу, добавим вращение (ну и поменяем маркер с круга на что-нибудь поинтереснее). В качестве маркера у нас будет ракета с шириной 48 и длиной 24 . Поскольку по умолчанию точкой привязки маркера является левый верхний угол, нам необходимо смещать его, чтобы привязка была к центру маркера. Также необходимо учитывать это при вращении, ведь оно тоже по умолчанию происходит вокруг левого верхнего угла. Со смещением вроде разобрались. Теперь перейдём непосредственно к вращению, здесь нам поможет определение касательной , угол будем определять с помощью арктангенса.

Функция translateAlong(path) , определяющая интерполятор будет выглядеть следующим образом:

Function translateAlong(path) { var l = path.getTotalLength(); var t0 = 0; return function(i) { return function(t) { var p0 = path.getPointAtLength(t0 * l);//previous point var p = path.getPointAtLength(t * l);////current point var angle = Math.atan2(p.y - p0.y, p.x - p0.x) * 180 / Math.PI;//angle for tangent t0 = t; //Shifting center to center of rocket var centerX = p.x - 24, centerY = p.y - 12; return "translate(" + centerX + "," + centerY + ")rotate(" + angle + " 24" + " 12" +")"; } } }
Реализацию можно посмотреть здесь.

Графика SVG может быть анимирована с помощью элементов анимации. Эти элементы были первоначально определены в спецификации анимации SMIL ; к ним относятся:

  • — позволяет задать анимацию для скалярных атрибутов и свойств на определенный промежуток времени;
  • — является удобным сокращением для анимации, с помощью которого можно присваивать значения анимации нечисловым атрибутам и свойствам, таким как свойства видимости;
  • — передвигает элемент вдоль траектории движения;
  • — изменяет значение цвета конкретных атрибутов или свойств за определенный промежуток времени. Обратите внимание, что использование элемента является устаревшей практикой по сравнению с использованием элемента анимации для определения свойств, которые могут принять значения цвета. Даже при том, что он по-прежнему присутствует в спецификации SVG 1.1 , в этой же спецификации было четко задекларировано, что он устарел; из спецификации SVG-2 он был полностью удален.

В дополнение к элементам анимации, определенным в спецификации SMIL, SVG включает в себя расширения, совместимые со спецификацией SMIL -анимации; эти расширения включают атрибуты, которые расширяют функциональные возможности элемента и дополнительных элементов анимации.

Расширения SVG включают:

  • — позволяет задавать анимацию одному из атрибутов преобразований SVG за определенный промежуток времени, например для атрибута transform ;
  • path (атрибут) — позволяет любой функции синтаксиса данных пути SVG быть указанной в атрибуте пути к элементу animateMotion (SMIL-анимация позволяет использовать в атрибуте пути только подчиненный набор синтаксиса данных пути SVG ).

Мы поговорим об animateMotion в следующем разделе:

  • — используется в сочетании с элементом animateMotion для ссылки на траекторию движения, которая должна использоваться, как и траектория движения. Элемент mpath включается внутри элемента animateMotion , перед закрывающим тегом;
  • keypoints (атрибут ) — используется в качестве атрибута для animateMotion , чтобы обеспечить точный контроль скорости перемещения анимированного элемента вдоль траектории;
  • rotate (атрибут ) — используется в качестве атрибута для animateMotion , чтобы контролировать поворачивается ли объект автоматически таким образом, чтобы его точки х-оси поворачивались в том же (или обратном ) направлении, что и направление касательного вектора пути движения. Этот атрибут является ключом к созданию движения вдоль пути, которое будет работать так, как вам нужно. Подробнее об этом в разделе animateMotion .

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

Для чего используется SVG-анимация?

Для SVG можно задать стили и анимацию с помощью CSS (слайдов ). В принципе, любая анимация преобразования или перехода, которая может быть применена к элементу HTML , также может применяться к элементу SVG . Но существуют некоторые свойства SVG , которые не могут быть анимированы через CSS , однако это можно сделать непосредственно через SVG .

Траектория SVG , например, определяется набором данных (атрибут d=»» ), которые определяют форму этой траектории. Эти данные могут быть изменены и анимированы через SMIL , но не через CSS .

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

Таким образом, многие эффекты анимации на текущий момент просто не могут быть реализованы с помощью CSS . Этот пробел может быть восполнен либо с помощью JavaScript , либо с помощью декларативной SVG анимации, полученной из SMIL .

Если вы предпочитаете использовать JavaScript , я рекомендую вам snap.svg Дмитрия Барановского, который называют «jQuery для SVG «.

Или, если вы предпочитаете более изысканный подход к анимации, вы можете использовать элементы SVG , которые мы рассмотрим в этом руководстве!

Еще одно преимущество SMIL над JS -анимацией заключается в том, что JS не работает, когда SVG встроен в качестве img или используется в качестве background-image в CSS . SMIL -анимация работает в обоих случаях (или ожидается, что вскоре будет поддерживаться браузерами ).

На мой взгляд, это существенное преимущество. Вы можете найти для себя и другие причины остановить свой выбор именно на SMIL . Эта статья представляет собой руководство, которое поможет вам начать работу со SMIL уже сегодня.

Поддержка браузеров и альтернативные варианты

SMIL довольно широко поддерживается браузерами. Он работает во всех браузерах за исключением Internet Explorer и Opera Mini . Чтобы получить исчерпывающую информацию относительно поддержки браузерами, вы можете ознакомиться с таблицей совместимости или «Могу ли использовать» .

Если вам нужно обеспечить запасной вариант для SMIL анимации, вы можете проверить наличие поддержки браузера с помощью Modernizr . Если SMIL не поддерживается, вы можете обеспечить своего рода альтернативный вариант (JavaScript анимация, альтернативный подход и т.д .).

Указание цели анимации с помощью xlink:href

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

Чтобы указать цель, вы можете использовать атрибут xlink:href . Атрибут принимает URI -ссылку на элемент, который является объектом данной анимации, и который, следовательно, будет изменяться в течение определенного времени. Целевой элемент должен быть частью текущего фрагмента SVG документа:

Если до этого вы имели дело с элементами анимации SVG , они, вероятно, встречались вам как вложенные элементы внутри другого элемента, который они должны анимировать. Это предусматривается спецификацией.

Если использование атрибута xlink:href не предусмотрено, то целевым элементом будет родительский элемент первого следующего вверх уровня от текущего элемента анимации:

Таким образом, если вы захотите «инкапсулировать » анимацию в элемент, к которому она применяется, вы можете сделать именно это. А если вы хотите, чтобы элементы анимации хранились в другом месте документа, вы можете сделать это, при этом указав цель для каждого элемента анимации с помощью xlink:href — оба способа работают одинаково корректно.

Указание целевого свойства анимации с помощью attributeName и attributeType

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

Например, если вы хотите задать анимацию для позиции центра по оси х, вы делаете это, указав cx в качестве значения атрибута attributeName .

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

Это то, что мне не совсем нравится, и, я думаю, что в этом CSS как раз имеет преимущество над SMIL . Но опять же, из-за значений, возможных для других атрибутов анимации (об этом чуть далее ), имеет смысл определять только одно имя атрибута за раз, в противном случае, если определить еще несколько значений атрибутов, работать с ними станет слишком сложно.

При указании имени атрибута, вы можете добавить префикс XMLNS (сокращение от пространство имен XML ) для обозначения пространства имен атрибута.

Пространство имен также можно задать с помощью атрибута attributeType . Например, некоторые атрибуты принадлежат пространству имен CSS (что означает, что атрибут может быть также найден как свойство CSS ), другие — только пространству имен XML .

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

Если значение для attributeType четко не установлено или установлено auto, браузер должен сначала произвести поиск по списку свойств CSS , и если ничего не найдено — поиск в пространстве имен XML элемента по умолчанию.

Например, следующий фрагмент задает анимацию для непрозрачности прямоугольника SVG . Поскольку атрибут opacity также доступен как свойство CSS , для attributeType установлено пространство имен CSS :

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

Установка анимации изменения атрибута элемента с одного значения к другому в течение некоторого времени с указанием конечного состояния: from, by, to, dur и fill

Давайте начнем с перемещения круга из одного места в другое. Мы собираемся сделать это, изменив значение его атрибута cx (который определяет положение его центра по оси х ).

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

Для того чтобы произвести изменение значения от одной величины к другой в течение определенного периода времени, используются атрибуты from, to и dur . В дополнение к ним вы также можете указать, когда анимация должна запускаться — для этого используется атрибут begin :

В приведенном выше примере мы определили круг, а затем вызывали анимацию для этого круга. Центр круга перемещается из исходного положения с координатами 50 единиц в точку с координатами 450 единиц по оси х.

Для атрибута begin мы устанавливаем значение click . Это означает, что круг будет начинать перемещаться после нажатия курсора мыши. Вы можете установить для этого атрибута определенное время. Например, begin=»0s» будет запускать анимацию сразу после загрузки страницы.

Вы можете задержать старт анимации, установив положительное значение времени, например, begin=»2s» будет запускать анимацию через две секунды после нагрузки страницы.

Еще более интересно, что вы можете определить для атрибута begin такое значение, как click + 1s , которое будет запускать анимацию через одну секунду после клика мышью!

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

Атрибут dur аналогичен атрибуту CSS animation-duration .

Атрибуты from и to аналогичны кифреймам from и to блока анимации @keyframe CSS :

@keyframes moveCircle { from { /* значение начала анимации */ } to { /* значение конца анимации */ } }

Атрибут fill (который, к сожалению, назван так же, как другой атрибут fill, определяющий цвет заливки элемента ) похож на свойство animation-fill-mode , которое определяет, должен ли элемент возвращаться к исходному состоянию после завершения анимации.

Его значения в SVG аналогичны тем, которые используются в CSS , за исключением использования различных имен:

  • freeze: Значение, которое указывает заморозить состояние эффекта на том, которое было при последнем значении продолжительности анимации. Эффект анимации «замораживается » до тех пор, пока документ не будет закрыт (или пока анимация не будет перезапущена );
  • remove: Эффект анимации удаляется (больше не применяется ), по завершению действия анимации, заданного продолжительностью. После завершения анимации она больше не применяется к целевому элементу (если только анимация не будет перезапущена ).

Попробуйте изменить значения в этой демо-версии, чтобы увидеть, как это повлияет на анимацию:
HTML:

CSS:

Результат

Атрибут by используется, чтобы указать относительное смещение для анимации. Как следует из названия, вы можете использовать его, чтобы указать значение, которое будет задавать изменение анимации.

Данный эффект заметен, в основном только когда вы изменяете продолжительность анимации от одного цикла к другому, подобно тому, как работает функция CSS steps().

В SVG эквивалентом функции CSS steps() является calcMode=»discrete» . Мы доберемся до атрибута calcMode=»discrete» чуть позже.

Перезапуск анимации с помощью restart

Вам может понадобиться заблокировать перезапуск анимации, пока она активна. Для этого в SVG предусмотрен атрибут restart.

Вы можете установить для него одно из трех возможных значений:

  • always: Анимация может быть перезапущена в любой момент. Это значение по умолчанию;
  • whenNotActive: анимация может быть перезапущена, только когда она неактивна (то есть по завершении периода продолжительности анимации ). Попытки перезапустить анимацию во время действия анимации игнорируются;
  • never: Элемент не может быть перезапущен, пока не перезагружен его родительский контейнер. (В случае с SVG, так как родительским контейнером является SVG -фрагмент документа, то анимация не может быть перезапущена, пока не перезагружен документ ).

Имена анимации и их синхронизации

Предположим, мы хотим задать анимацию для положения и цвета круга, таким образом, чтобы изменение цвета происходило в конце анимации перемещения. Мы можем сделать это, установив значение begin для анимации изменения цвета равным длительности анимации перемещения; так мы, как правило, делаем в CSS .

Однако SMIL имеет отличную функцию обработки событий. Я уже упоминала, что атрибут begin принимает такие значения, как click + 5s . Это значение называется «значением события «, и в данном случае оно состоит из события, за которым следует «значение часов «.

Самая интересная здесь вторая часть — «значение часов «. Почему оно не называется просто «значение времени «? Ответ заключается в том, что вы можете использовать это значение буквально, как часы : вы можете установить «10min » или «01:33 «, что будет эквивалентно «1 минуте и 33 секундам «, или даже «02:30:03 » (2 часа, 30 минут и 3 секунды ). На момент написания этой статьи, значения часов не полностью реализованы в большинстве браузеров.

Так что, если бы в предыдущей демонстрации мы использовали click + 01:30 , то в случае реализованной поддержки браузером, анимация бы запустилась через 1 минуту и 30 секунд после клика мыши.

Еще один вид значения, которое может принимать этот атрибут — это ID другой анимации, за которым следует обозначение события. Если у вас есть два (или более ) эффекта анимации (независимо то того, применяются ли они к одному элементу или нет! ), и вы хотите синхронизировать их таким образом, чтобы один из них начинался в зависимости от стадии исполнения другого, вы можете сделать это, даже не зная продолжительность другой анимации.

Например, в следующем примере, синий прямоугольник начинает движение через 1 секунду после начала анимации круга. Это делается путем предоставления каждому элементу анимации ID , а затем использования этого ID с событием begin , как это показано в следующем коде:

begin=»circ-anim.begin + 1s» указывает браузеру начать анимацию прямоугольника через 1 секунду после начала анимации круга.

Вы можете увидеть все это в этой демонстрации:

HTML:

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

CSS:

Результат

Вы также можете запустить анимацию прямоугольника по завершении анимации круга, используя событие end :

Вы можете даже запустить ее до завершения анимации круга:

Повторяющаяся анимация с помощью repeatCount

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

Таким образом, если мы хотим повторить анимации круга два раза, код должен выглядеть следующим образом:

Вы можете увидеть это в демонстрации. Я установила количество повторений для круга — 2 и для квадрата indefinite .
HTML:

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Обратите внимание, что анимация рестартует с первоначального значения from , а не со значения, которого она достигла по завершении цикла. К сожалению, SMIL не позволяет нам задать путь туда и обратно между начальным и конечным значениями, как мы можем сделать это с помощью CSS анимации.

В CSS свойство animation-direction определяет, должна ли анимация проигрываться в обратном направлении или каждый цикл стартует с нулевой точки.

Значение animation-direction: alternate означает, что четные циклы анимации проигрываются в обычном направлении, а нечетные воспроизводятся в обратном направлении. Это означает, что первый цикл будет проигрываться от начала до конца, а второй — с конца обратно к началу, третий цикл снова будет проигрываться от начала к концу и так далее.

Чтобы сделать это в SMIL , вам придется использовать JavaScript , чтобы изменять значения атрибутов from и to . Джон МакПартленд из Big Bite Creative некоторое время назад опубликовал статью , в которой описал, как он сделал это для анимации иконок меню, над которой он работал.

Вот отличная, простая анимация, повторяющаяся бесконечное количество раз, с использованием задержки, созданная Майлзом Иламом :

HTML:

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Ограничение времени повторения анимации с помощью repeatDur

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

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

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

Его синтаксис похож на значение часов, но вместо того, чтобы отсчитывается от других событий анимации или событий взаимодействия, в данном случае время отсчитывается от начала (загрузки ) документа.

Например, следующий фрагмент остановит повторение анимации через 1 минуту и 30 секунд после начала (загрузки ) документа:

А это демо, иллюстрирующее данный атрибут:
HTML:

Результат

Синхронизация анимации в зависимости количества повторений

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

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

В следующем примере анимация прямоугольника запускается на втором повторении анимации круга:

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

Управление значениями кифреймов анимации: keyTimes и values

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

Например, если вы задаете анимацию для смещения элемента слева, вместо указания изменения смещения непосредственно от 0 до 300, вы можете анимировать его так, что смещение принимает определенные значения в определенном фрейме следующим образом:

@keyframes example { 0% { left: 0; } 50% { left: 320px; } 80% { left: 270px; } 100% { left: 300px; } }

0%, 20%, 80% и 100% — это фреймы анимации, а значения в блоке каждого фрейма являются значениями для каждого из них. Описанный выше эффект является одним из элементов анимации подпрыгивающего мячика.

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

Чтобы указать кифреймы, используется атрибут keyTimes . И, чтобы указать значение свойства анимации для каждого фрейма, используются атрибуты values . Соглашение об именах в SMIL довольно удобное.

Если вернуться к нашему перемещающемуся кругу и использовать значения, аналогичные описанным выше кифреймам CSS , то код будет выглядеть следующим образом:

Что мы сделали?

Первое, что нужно отметить — время и промежуточные значения кифреймов задаются в виде списков. Атрибут keyTimes — разделенный точками с запятой список значений времени, используемый для управления этапами анимации. Каждое время в списке соответствует значению в списке атрибутов values , и определяет, когда это значение используется в функции анимации.

Каждое значение времени в списке keyTimes задается как десятичное число от 0 до 1 (включительно ), представляющее собой пропорциональный сдвиг по времени в проигрывании элемента анимации. Таким образом, keyTimes работает так же, как его аналоги в CSS , за исключением того, что мы определяем его в виде десятичной дроби, а не в процентах.

Ниже приведена демонстрация для данного кода.
HTML:

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Следует отметить, что, если используется список значений, то анимация будет применяться в соответствии с указанными в нем значениями. В этом случае все атрибуты from, to и by будут игнорироваться.

Управление темпом анимации с помощью пользовательских корректив: calcMode и keySplines

Сейчас я снова прибегну к сравнению CSS и SMIL , потому что синтаксис и концепцию SMIL вам будет гораздо проще понять, если вы уже знакомы с анимацией CSS .

В CSS вы можете изменить равномерное проигрывание анимации по умолчанию и указать пользовательскую функцию корректировки, которая будет управлять анимацией с помощью свойства animation-timing-function.

Функция тайминга может определяться одним из нескольких предопределенных ключевых слов или функций cubic b;zier . Последняя может быть создана при помощи инструментов, наподобие этого, разработанного Леей Веру .

В SMIL темп анимации задается с помощью атрибута calcMode . По умолчанию его значение для всех элементов анимации — linear , кроме animateMotion (мы вернемся к нему позже ). Кроме значения linear , вы можете установить также значения: discrete, paced или spline .

  • discrete указывает, что функция анимации переходит от одного значения к другому без интерполяции. Это похоже на функцию CSS steps() ;
  • paced похоже на значение linear , кроме того, что при этом игнорируются любые промежуточные значения, и изменение времени выполнения анимации определяется в keyTimes ;
  • spline производит интерполяцию от одного значения в списке значений к другому в соответствии с функцией времени, определяемой кубическим сплайном Безьера. Точки сплайна определяются в атрибуте keyTimes , а точки перехода для каждого интервала определяются в атрибуте keySplines .

Вы, наверное, заметили, что я упомянула новый атрибут: keySplines . Что же делает атрибут keySplines ?

Опять же это аналогично CSS .

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

@keyframes bounce { 0% { top: 0; animation-timing-function: ease-in; } 15% { top: 200px; animation-timing-function: ease-out; } 30% { top: 70px; animation-timing-function: ease-in; } 45% { top: 200px; animation-timing-function: ease-out; } 60% { top: 120px; animation-timing-function: ease-in; } 75% { top: 200px; animation-timing-function: ease-out; } 90% { top: 170px; animation-timing-function: ease-in; } 100% { top: 200px; animation-timing-function: ease-out; } }

Вместо функции корректировки мы можем использовать соответствующие функции cubic-bezier :

  • ease-in = cubic-bezier(0.47, 0, 0.745, 0.715);
  • ease-out = cubic-bezier(0.39, 0.575, 0.565, 1)

Давайте начнем с определения ключевых интервалов времени и списка значений для нашего оранжевого круга, чтобы создать тот же эффект подпрыгивающего мячика:

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

Атрибут keySplines принимает набор контрольных точек b;zier , связанных со списком keyTimes , определяющим кубическую функцию Безье, которая управляет интервалами с разным темпом. Значение атрибута представляет собой разделенный точками с запятой список описаний контрольных точек.

Каждое описание контрольной точки представляет собой набор из четырех значений: x1 y1 x2 y2, описывающий координаты контрольных точек b;zier для одного сегмента времени. Их значение должно находиться в диапазоне от 0 до 1, и для calcMode должно быть установлено значение spline , иначе атрибут игнорируется.

Вместо использования в качестве значений функции cubic-bezier, keySplines принимает координаты двух контрольных точек, которые используются для построения кривой. Данные контрольные точки вы можете видеть на приведенном ниже скриншоте, взятом из инструмента Леи.

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

В SMIL эти значения можно разделять либо запятыми с дополнительным пробелом, либо просто пробелами. Значения keyTimes , которые определяют соответствующий сегмент, являются «опорными точками » b;zier , а значения keySplines являются контрольными точками. Таким образом, контрольных точек должно быть задано на одну меньше, чем keyTimes :


Если мы вернемся к примеру подпрыгивающего мячика, координаты контрольной точки для функций ease-in и ease-out показаны на следующих изображениях:
Таким образом, переведя все это в элемент анимации SVG , мы получим следующий код:

Ниже приводится демо-версия, но убедитесь, что вы запустили ее в Firefox , а не в Chrome , потому что в его последней версии найден а ошибка, из-за которой демо-версия не будет работать корректно:

HTML:

Нажите на круг, чтобы запустить анимацию.

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Если вы хотите указать только общую функцию корректировки скорости для всей анимации, без промежуточных значений, вы все равно должны указать кифреймы, используя атрибут keyTimes , однако вам будет достаточно задать только начальный и конечный кифреймы, а именно 0; 1 — без промежуточных values .

Добавляемые и накапливающие анимации: additive и accumulate

Иногда нам нужно определить анимацию, которая начинается там, где закончилась предыдущая анимация; или анимацию, которая использует накопительную сумму предыдущих анимаций в качестве значения для начала воспроизведения. Для этого в SVG существуют два атрибута, называющиеся соответствующим образом: additive и accumulate .

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

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

Итак, вернемся к нашему кругу. Для него начальное положение cx равно 50 . Если вы устанавливаете значения from=»0″ to=»100″ , то ноль фактически означает начальное значение 50, а 100 — начальное значение 50+100. То есть на практике получается, что вы устанавливаете «from=»50″ to=»150» .

Сделав это, мы получим следующий результат:

HTML:

Нажмите на круг, чтобы запустить анимацию.

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Это все, что делает атрибут additive . Он просто определяет, будут ли значения from и to связаны с текущим значением атрибута или нет. Атрибут принимает одно из двух значений: sum и replace .

Последнее значение присваивается по умолчанию, и это, как правило, означает, что заданные значения from и to заменяют текущие / исходные значения, что в конечном итоге может привести к резкой смене позиции анимируемого элемента в начале анимации.

(Попробуйте в приведенном выше примере заменить sum на replace , и вы увидите, что получится ).

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

Атрибут accumulate контролирует, учитывается ли предыдущее конечное значение атрибута. По умолчанию его значение none , это означает, что, когда анимация повторяется, то это происходит с самого начала, не учитывая окончания предыдущей итерации.

Однако вы можете установить его на sum . Это будет означать, что каждый новый цикл анимации связан с тем, где завершился предыдущий цикл.

Таким образом, если мы вернемся к предыдущей анимации и укажем accumulate=»sum» , мы получим следующий результат:
HTML:

Нажмите на круг, чтобы запустить анимацию.

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Имейте в виду, что атрибут accumulate игнорируется, если значение целевого атрибута не поддерживает добавление, или если элемент анимации не повторяется. Он также будет игнорироваться, если функция анимации задается только с одним атрибутом to .

Указание окончания анимации с помощью end

Кроме определения того, когда анимация должна начинаться, можно также указать, когда она должна заканчиваться через атрибут end . Например, вы можете установить, чтобы анимация повторялась бесконечно, а затем остановить ее, когда начинается анимация другого элемента.

Атрибут end принимает значения, аналогичные тем, которые имеет атрибут begin . Вы можете указывать абсолютные или относительные значения времени / интервалы, значения повторений, значения событий и т.д.

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

Анимация оранжевого круга закончится, когда начнется анимация зеленого круга — таким образом, когда вы нажмете на зеленый круг, оранжевый круг остановится.

HTML:

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; }

Результат

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

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

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; }

Результат

Определение интервалов анимации с использованием нескольких значений begin и end

В самом деле, оба атрибута и begin , и end принимают разделенный запятыми список значений. Каждое значение в атрибуте begin будет иметь соответствующее значение в атрибуте end , что образует активные и не активные интервалы анимации.

Это можно представить, как движущийся автомобиль, у которого колеса то активны, то не активны какое-то время, в зависимости от того, движется ли автомобиль или стоит на месте.

Вы даже можете создать анимацию движущегося автомобиля, применив соответствующие эффекты: один для перемещения автомобиля или движения его вдоль пути, который использует добавляемую и накапливаемую анимацию; второй — для вращения колес в интервалах, которые будут синхронизированы с перемещением.

Примером установки нескольких значений времени начала и конца анимации (т.е. интервалов ) является следующая демонстрация, где прямоугольник поворачивается, исходя из определенных интервалов, переходя от активного состояния в не активное.
(Перезапустите демонстрацию, если вы пропустили анимацию ).
HTML:

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; }

Результат

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

Также отмечу, что, даже если вы установите для repeatCount значение indefinite , оно будет перекрыто значениями end , и анимация не будет повторяться бесконечно.

Ограничение продолжительности действия элемента с помощью min и max

Так же, как вы можете ограничить количество или время повторений анимации, вы можете ограничить и продолжительность действия анимации.

Атрибуты min и max указывают минимальное и максимальное значение продолжительности анимации соответственно. Они дают нам возможность регулировать нижний и верхний предел продолжительности действия элемента. Оба атрибута принимают значения часов.

min указывает величину минимального значения продолжительности действия анимации, замеряемую по времени действия элемента. Значение этого атрибута должно быть больше или равно 0 (значение по умолчанию, при котором продолжительность действия вообще не ограничивается ).

В max значение часов указывает величину максимального значения продолжительности действия, измеряемую по времени действия элемента. Его значение также должно быть больше 0. Значение по умолчанию для max — indefinite . Оно не ограничивает продолжительность действия вообще.

Если указаны оба атрибута, то значение max должно быть больше или равно значению min . Если это требование не выполняется, то оба атрибута игнорируются.

Но что же определяет продолжительность действия элемента? Мы упомянули ранее, что существует продолжительность повторений анимации, это кроме «простой продолжительности «, которая является продолжительностью анимации без повторения (указывается с помощью dur ).

Так как все это работает вместе? Что является более приоритетным? И как насчет атрибута end , он переназначает значения или просто заканчивает анимацию?

Все это работает следующим образом. Браузер сначала вычисляет продолжительность действия на основе значений dur, repeatCount, repeatDur и end . После этого запускается вычисление продолжительности согласно указаниям значений min и max .

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

  • Если вычисленная первой продолжительность больше, чем значение max, продолжительность действия элемента определяется равной значению max ;
  • Если вычисленная первой продолжительность меньше, чем значение min , продолжительность действия элемента будет равна значению min и поведение элемента заключается в следующем;
  • Если продолжительность повторений (или простая продолжительность, если элемент не повторяется ) элемента больше, чем min , то элемент проигрывается стандартное время (включающее min ) продолжительности действия;
  • В противном случае элемент проигрывается стандартное время продолжительности повторений (или простой продолжительности, если элемент не повторяется ), а затем замораживается и не выводится вовсе, в зависимости от значения атрибута fill .

Это подводит нас к вопросу о том, как браузер фактически вычисляет продолжительность действия. Для краткости я не буду вдаваться в подробности.

Но спецификация содержит очень подробную таблицу, в которой приведены различные комбинации атрибутов dur , repeatCount, repeatDur и end и то, как будет определяться продолжительность действия анимации, исходя из каждой комбинации.

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

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

Это означает, что значение min не будет иметь заметного влияния на протекание анимации элемента.

Пример : трансформация контуров

Одним из атрибутов, которые могут быть анимированными через SMIL (но для которых нельзя задать анимацию через CSS ), является атрибут из SVG — d (сокращенно от «data» — данные ).

Атрибут d содержит данные, которые определяют контуры формы или фигуры, которую вы создаете. Эти данные контура состоят из набора команд и координат, которые указывают браузеру, где и как рисовать точки, дуги и линии, которые составляют окончательный контур.

Анимируя этот атрибут, мы можем трансформировать контуры SVG и создавать эффекты метаморфоз фигур .

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

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

Чтобы анимировать контур SVG , нам нужно указать для атрибута attributeName значение d , а затем установить значения from и to , которые определяют начальную и конечную фигуры. Вы также можете использовать атрибут values , чтобы определить любые промежуточные значения, которые должен принимать контур при трансформации.

Для краткости, я не буду вдаваться в подробности относительно того, как это сделать. Вместо этого, вы можете прочитать эту прекрасную статью Ноа Блона , в которой он объясняет, как он создал трансформирующуюся фигуру, использую . Вот демонстрация созданной Ноа анимации:
HTML:

CSS:

body { height: 100vh; text-align: center; box-sizing: border-box; padding-top: calc(50vh - 56px); } img, svg { display: inline-block; vertical-align: middle; } svg { height: 38px; width: 38px; display: inline-block; }

// Injecting the image helps keep them in sync $(document).ready(function(){ $("img").attr("src", "http://dab1nmslvvntp.cloudfront.net/wp-content/uploads/2014/08/1407310358spinner-cropped.gif"); });

Результат

А вот еще один пример морфинга Феликса Орнуа :
HTML:

CSS:

Результат

Вы даже можете использовать трансформирующийся контур для отсечения окружающего фона и обозначения определенной фигуры. Вот пример Хизер Бушель :
HTML:

SCSS:

$base: #C8C8A9; $primary: #FE4365; body { background: $base; text-align: center; } svg { position: absolute; top: 50%; left: 50%; margin-top: -60px; margin-left: -60px; } .logo { fill: $primary; } .clip { animation: slide 8s infinite; } @keyframes slide { from { transform: translateY(-135px); } 50% { transform: translateY(-5px); } to { transform: translateY(-135px); } }

Результат

Анимация вдоль произвольного пути: Элемент

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

Элемент принимает те же атрибуты, что и упомянутые ранее элементы, плюс еще три: keyPoints, rotate и path . Кроме того, есть одно отличие, которое относится к атрибуту calcMode . Для элемента его значение по умолчанию является paced , а не linear .

Указание пути движения с помощью атрибута path

Атрибут path используется, чтобы указать траекторию движения. Он представляется в том же формате и интерпретируется аналогичным образом, как и атрибут d для элемента path .

Эффект анимации движения вдоль траектории заключается в добавлении дополнительной матрицы преобразования к текущей матрице связанного объекта, что дает возможность задать перемещение объекта вдоль осей х и у текущей пользовательской системы координат через вычисление значений X и Y для каждого момента времени.

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

Мы хотим задать анимацию перемещения нашего круга вдоль пути, который выглядит следующим образом:


Код, необходимый, чтобы запустить движение круга по этому пути, следующий:

Есть одна вещь, на которую я хочу обратить ваше внимание: координаты в данных пути. Путь начинается с перемещения (M) в точку с координатами (0, 0), после чего начинает описывать кривую (с) к другой точке.

Важно, чтобы вы понимали, что точка (0, 0) — это на самом деле исходное положение круга, независимо от того, где он находится к началу анимации перемещения — это НЕ верхний левый угол системы координат. Как мы уже упоминали выше, координаты для атрибута path привязаны к текущей позиции элемента!

Результат приведенного выше кода будет следующим:
HTML:

CSS:

* { box-sizing: border-box; } .cont { height: 100vh; padding: 20vmin; -webkit-filter: contrast(10); background-color: white; } svg { width: 100%; height: 100%; opacity: 0.9; -webkit-filter: blur(3px);}

Результат

Если бы вы указали начало пути в точке с координатами, отличными от (0, 0), тогда круг перед началом анимации совершал бы резкий скачок в точку с указанными координатами.

Например, предположим, что вы нарисовали контур в Illustrator , а затем экспортировали данные этого контура, чтобы использовать их в качестве траектории движения (это то, что сделала я, когда в первый раз работала с этим элементом ); экспортируемый путь может выглядеть примерно следующим образом:

Отправной точкой пути в этом случае будет (100.4, 102.2). Если бы мы использовали эти данные в качестве траектории движения, то круг бы резко перепрыгнул перед началом анимации примерно на 100 единиц вправо и на 102 единицы вниз, а затем начал движение вдоль пути относительно новой позиции. Поэтому тщательно проверяйте данные, когда готовите траекторию движения для анимации.

Атрибуты from, by, to и values (если используются ) указывают форму текущего холста, который представляет траекторию движения.

Указание траектории движения с помощью элемента

Существует также еще один способ указать траекторию движения. Вместо того чтобы использовать связанный атрибут path , вы можете ссылаться на внешний путь с помощью элемента . — дочерний элемент от элемента , он может ссылаться на внешний путь с помощью атрибута xlink:href :

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

Обратите внимание, что в соответствии со спецификацией:

Различные точки (х, у) формы предоставляют дополнительную матрицу преобразования CTM для связи с объектом, в результате чего осуществляется перемещение вдоль осей х и у текущей системы координат пользователя через вычисление значений формы (х, у) для каждого отрезка времени. Таким образом, связанный объект перемещается в течение определенного времени, при этом путь движения объекта смещается к исходной системе координат текущего пользователя. Дополнительные преобразования применяются на переходе любых преобразований, благодаря свойству целевого элемента transform, или на переходе любой анимации этого атрибута, благодаря элементу целевого элемента animateTransform.

Опять же, круг «размножается » или «преобразуется » в другие круги в других точках, согласно координатам данных пути.

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

HTML:

Нажмите на круг, чтобы запустить анимацию.

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Видите, как круг следует по траектории той же формы, но в другом месте? Это связано с тем, что позиция круга преобразуется согласно значениям данных пути.

Один из способов решить эту проблему — это установить круг в точке (0, 0 ), таким образом, чтобы, когда используются данные пути для его преобразования, он начинал движение и перемещался так, как ожидалось.

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

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

HTML:

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Переопределение правил

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

Правила переопределения для animateMotion :

  • Что касается определения траектории движения, элемент mpath переопределяет атрибут path , который в свою очередь переопределяет values , а values переопределяют from, by и to ;
  • Что касается определения точки, соответствующей атрибутам keyTimes , атрибут keyPoints переопределяет атрибут path, path переопределяет values , а values переопределяют from , by и to .

Установка ориентации элемента вдоль траектории движения с помощью rotate

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

Иконка автомобиля в следующем примере создана Freepik’ом .

В этом примере я заменила круг группой с идентификатором «car «, в которой содержится элемент, составляющий группу.

Затем, для того чтобы избежать проблем с движением вдоль пути, о которых упоминалось выше, я применила к автомобилю преобразование, которое перемещает его на определенное расстояние так, что начальное положение устанавливается в точке (0, 0 ).

Значения внутри преобразований на самом деле являются координатами точки, в которой начинает прокладываться первая траектория автомобиля (сразу после команды перемещения М ).

Затем автомобиль начинает движение вдоль траектории. Но … вот, как выглядит это движение:
HTML:

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Ориентация автомобиля фиксируется, и не меняется в любой точке траектории движения. Для того чтобы изменить это, нам нужно использовать атрибут rotate .

Атрибут rotate принимает одно из трех значений:

  • auto: указывает, что объект поворачивается на угол к направлению (т.е. вектору касательной ) траектории движения;
  • auto-reverse: указывает, что объект поворачивается на угол к направлению (т.е. вектору касательной ) траектории движения плюс 180 градусов;
  • число: указывает, что к целевому элементу применяется постоянное преобразование поворота, где угол поворота равен указанному числу в градусах.

Чтобы скорректировать ориентацию автомобиля в приведенном выше примере, мы начнем с установки значения вращения auto . И получим следующий результат:

HTML:

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Если вы хотите, чтобы автомобиль перемещался с внешней стороны области, очерченной траекторией, это делается с помощью значения auto-reverse .

Click on the circle to animate it.

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Так уже намного лучше, но у нас еще есть одна проблема: автомобиль едет вверх колесами! Для того чтобы изменить это, мы должны перевернуть его вдоль собственной оси ординат. Это может быть сделано путем масштабирования с коэффициентом «-1 » вдоль этой оси.

Так что, если мы применим преобразование к g с ID car , автомобиль будет перемещаться так, как нам нужно. Преобразование масштаба должно только чередоваться с преобразованием, которое мы применяли ранее.

И окончательная демо-версия будет выглядеть следующим образом:
HTML:

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } p { color: #aaa; text-align: center; margin: 2em 0; }

Результат

Управление отдалением анимации от траектории движения с помощью keyPoints

Атрибут keyPoints дает нам возможность указать отдаление от траектории движения для каждого из указанных значений keyTimes . Если атрибут keyPoints указан, то это приводит к тому, что keyTimes применяются к значениям keyPoints , а не к точкам, указанным в массиве атрибута values или точкам атрибута path .

keyPoints принимает разделенный точками с запятой список десятичных значений от 0 до 1 и определяет, как далеко от траектории движения должен двигаться объект в момент времени, определенный соответствующими значениями keyTimes .

Расчеты расстояния определяются алгоритмами браузера. Каждое следующее значение в списке соответствует значению в списке атрибута thekeyTimes . Если задается список keyPoints , в нем должно быть ровно столько же значений, сколько и в списке keyTimes .

Атрибут keyPoints на момент написания данной статьи не поддерживался в Chrome и Firefox . Он пока еще не реализован, как и другие части спецификации, о которых я упоминала ранее.

Перемещение текста вдоль произвольного пути

Перемещение текста вдоль произвольного пути отличается от перемещения других элементов SVG вдоль пути. Чтобы анимировать текст, вам нужно будет использовать элемент , а не .

Во-первых, давайте разместим текст вдоль пути. Это можно сделать, вложив элемент внутрь элемента .

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

textPath затем будет ссылаться на фактический путь, который мы хотим использовать, как мы это делали в предыдущих примерах. Путь аналогично может быть либо выведен на холсте, либо определен внутри . Посмотрите приведенный ниже код:
HTML:

Текст, уложенный вдоль пути.

CSS:

Результат

Чтобы задать анимацию перемещения текста вдоль этого пути, мы будем использовать элемент для анимирования атрибута startOffset .

startOffset отображает смещение текста вдоль пути. 0% это начало пути; 100% — конец. Таким образом, если, например, смещение устанавливается на 50%, текст будет начинаться в середине пути. Я думаю, что вы уже догадались, что мы будем делать дальше.

Анимировав startOffset , мы создадим эффект движения текста вдоль пути. Посмотрите на код следующей демонстрации.

HTML:

Text laid out along a path.

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; } text { fill: deepPink; font-size: 2em; }

Результат

Анимация преобразований: Элемент

Элемент анимирует атрибут преобразования целевого элемента, тем самым позволяя анимации управлять его перемещением, масштабированием, вращением и / или наклоном. Он принимает те же атрибуты, что были перечислены для элемента , плюс дополнительный атрибут: type .

Атрибут type используется для указания типа преобразования, которое мы анимируем. Он принимает одно из пяти значений: translate, scale, rotate, skewX и skewY .

Атрибуты from, by и to принимают значения, выраженные через тот же синтаксис, который доступен для данного типа преобразования:

  • + Для type=»translate» , каждое отдельное значение выражается как [,];
  • + Для type=»scale» , каждое отдельное значение выражается как [,];
  • + Для type=»rotate», каждое отдельное значение выражается как [ ];
  • + Для type=»skewX» and type=»skewY» , каждое отдельное значение выражается как .

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

Атрибуты from и to указывают угол поворота (начало и конец ) и центр вращения. Для обоих, центр вращения остается тем же самым, конечно. Если вы не укажете центр, это будет левый верхний угол холста SVG . Демонстрация для приведенного выше кода выглядит следующим образом:
HTML :

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; }

Результат

Ниже приводится еще один веселый пример с одним animateTransform , созданный Габриелем :

HTML:

CSS:

* { margin: 0; padding: 0; } html, body { height: 100%; } body { background: #FC0; } svg { position: fixed; top: 20%; height: 60%; left: 20%; width: 60%; }

Результат

Анимировать одно преобразование довольно просто, однако все может стать действительно сложно и запутано, когда у нас включены несколько преобразований. Особенно потому, что один элемент animateTransform может переопределять другой, так что вместо последовательной серии эффектов мы в конечном итоге можем получить что-то совершенно противоположное.

Это, в дополнение к тому, насколько сложно осуществляется работа системы координат и преобразований SVG . Различных частных случаев может быть огромное количество, и их рассмотрение выходит за рамки данной статьи.

Для преобразования SVG я рекомендую использовать CSS преобразования. Последние решения отлично работают с SVG , так что SMIL может вам вовсе не понадобиться для анимации преобразований в SVG .

Элемент

Элемент set обеспечивает простое средство установки значения атрибута в течение определенного времени. Он поддерживает все типы атрибутов, в том числе и те, которые не могут быть интерполированы, например, строки и логические значения.

Элемент set является не добавляемым. Добавляемые и накапливаемые атрибуты не допускаются, и будут игнорироваться, если таковые указаны.

Так как используется, чтобы установить для элемента определенное значение в течение определенного времени, он принимает не все атрибуты, описанные ранее в этом руководстве. Например, он не содержит атрибутов from или by , так как их значения не изменяются прогрессивно в течение периода времени.

Для элемента set вы можете указать целевой элемент, имя и тип атрибута, значение to и анимацию тайминга, которой можно управлять с помощью: begin, dur, end, min,max, restart, repeatCount, repeatDur и fill .

Ниже приведен пример, который устанавливает после нажатия курсором мыши синий цвет вращающегося прямоугольника. Цвет остается синим на протяжении 3 секунд, а затем возвращается к первоначальному значению. Каждый раз, когда вы нажимаете на прямоугольник, запускается анимация, и цвет изменяется на 3 секунды.

HTML:

CSS:

svg { border: 3px solid #eee; display: block; margin: 1em auto; }

Результат

Элементы, атрибуты и свойства, которые могут быть анимированы

Не все атрибуты SVG могут быть анимированы, и не все атрибуты, которые могут быть анимированы, могут быть анимированы с использованием всех элементов анимации.

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

Заключение

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

В предыдущих уроках серии мы разбирались использованием векторной графики SVG в HTML. Теперь пришел черед рассмотреть анимацию SVG .

Основы

Анимация SVG выполняется с помощью элемента :

Мы добавляем элемент внутрь элемента , который будем анимировать. Элемент содержит следующие атрибуты:

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

from : опциональный атрибут. Определяет стартовое значение, по умолчанию используется текущее значение.

to : данный атрибут определяет направление анимации. В зависимости от заданного в атрибуте attributeName значения результат может различаться. В приведенном примере будет изменяться высота элемента.

dur : определяется длительность анимации. Значение нужно задавать в формате Clock Value Syntax . Например, 02:33 соответствует 2 минутам и 33 секундам, а 3h соответствует 3 часам. Для нашего примера мы определяем длительность анимации в 3 секунды.

То же самое мы проделываем с элементом , но для него будет анимировать атрибут радиуса (r).

Перемещение элементов

Для перемещения SVG элементов нужно только указать координаты x и y:

В примере мы перемещаем прямоугольник с 0 до 200 за 3 секунды. Также мы добавляем атрибут fill к элементу . Данный атрибут определяет как анимация будет действовать после завершения. В примере значение freeze вынуждает элемент оставаться там, где завершается анимация.

Также все действует и для элемента , но для него будем изменять атрибуты cx или cy:

Анимация нескольких атрибутов

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

Здесь мы анимируем для атрибута для элемента - радиус и ширину обводки.

Мы давно обещали сделать ролик про анимацию SVG элементов на страницах, но все как-то не удавалось. Сегодня мы наконец-то рады вам представить первый ролик из серии, в котором расскажем про варианты анимации SVG: с помощью CSS, SMIL и JavaScript (на примере Snap.svg).

На самом деле у нас с этим роликом было как с Мистралями. Не сложились обстоятельства для записи. Ну вот теперь наконец-то сложились.

SVG анимации

Попробуем еще разок собрать все вместе со ссылками. Существуют три способа анимации SVG элементов на странице, два из которых применимы и для HTML элементов. Я, конечно же, говорю про CSS и JavaScript анимации. Но для SVG можно еще использовать SMIL (Synchronized Multimedia Integration Language) анимации.

SMIL анимации

Это очень крутая технология если нам нужно анимировать path-ы и при этом хранить это все в одном SVG файле. Да, CSS анимации тоже можно включать в файл, но с их помощью нельзя анимировать атрибут d у path-ов, поэтому SMIL оказывается намного более интересной технологией. Собственно JavaScript тоже можно включать прямо в SVG файлы, но поддержка браузеров немного разная, поэтому нужно обязательно думать что и как использовать.

SMIL поддерживается во всех браузерах с незапамятных времен (с ранних версий), кроме Internet Explorer, который не поддерживает эти анимации до сих пор.

CSS анимации

Здесь все предельно ясно, мы уже давно привыкли использовать CSS для небольших анимаций HTML элементов. Тоже самое можно делать и с SVG: большинство атрибутов можно анимировать и поддержка браузеров значительно лучше . Ну потому что хотя бы Internet Exporer 10 узнал про такое явление, как CSS анимации.

JavaScript анимации

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

В некоторые даже включены возможности анимации, например в Snap.svg. Я бы всем советовал именно эту библиотеку, хотя многие привыкли работать с Velocity.js, такой подход тоже имеет право на существование.

В предыдущих уроках серии мы разбирались использованием векторной графики SVG в HTML. Теперь пришел черед рассмотреть анимацию SVG .

Основы

Анимация SVG выполняется с помощью элемента :

Мы добавляем элемент внутрь элемента , который будем анимировать. Элемент содержит следующие атрибуты:

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

from : опциональный атрибут. Определяет стартовое значение, по умолчанию используется текущее значение.

to : данный атрибут определяет направление анимации. В зависимости от заданного в атрибуте attributeName значения результат может различаться. В приведенном примере будет изменяться высота элемента.

dur : определяется длительность анимации. Значение нужно задавать в формате Clock Value Syntax . Например, 02:33 соответствует 2 минутам и 33 секундам, а 3h соответствует 3 часам. Для нашего примера мы определяем длительность анимации в 3 секунды.

То же самое мы проделываем с элементом , но для него будет анимировать атрибут радиуса (r).

Перемещение элементов

Для перемещения SVG элементов нужно только указать координаты x и y:

В примере мы перемещаем прямоугольник с 0 до 200 за 3 секунды. Также мы добавляем атрибут fill к элементу . Данный атрибут определяет как анимация будет действовать после завершения. В примере значение freeze вынуждает элемент оставаться там, где завершается анимация.

Также все действует и для элемента , но для него будем изменять атрибуты cx или cy:

Анимация нескольких атрибутов

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

Здесь мы анимируем для атрибута для элемента - радиус и ширину обводки.