Анимированные svg. Графическая анимация SVG
Использование списков в статье положительно сказывается как на SEO, так и на восприятии пользователем информации. Существует множество способов красиво отобразить маркеры (картинкой или с помощью CSS). Мы же рассмотрим достаточно простой, но стильный метод, как изменить маркеры списка на CSS.
Как это выглядит?
В этом случае нам не обойтись без новых технологий, а именно - CSS3 с поддержкой псевдокласса before. С помощью одних лишь только стилей и базовой верстки HTML мы преобразим наскучившие стандартные маркеры, не отвечающие современным стандартам.
В первом случае будем использовать маркированный список, который нам предлагает тег
- :
- Что у нас получилось.
- Неплохо, правда?
- Слева от текста число.
- Продолжение списка на необходимое нам количество полей.
- Элемент 1
- Элемент 2
- Элемент 1
- Элемент 2
- Изменение вида стандартного маркера для нумерованных списков
- Установка типа маркера для маркированных списков
- Установка изображения вместо маркера для элементов списка
- Кликните на значение свойства list-style-type
- Наблюдайте за сменой маркеров
- Используйте для своих списков наиболее подходящие маркеры
- Кофе
- Чай
- Кофе
- Чай
- Кофе
- Чай
- Кофе
- Чай
- Кофе
- Чай
- Кофе
- Чай
- Кофе
- Чай
- Кофе
- Чай
- Кофе
- Чай
- , а просто скрываются за краем окна браузера.
Свойство list-style-position указывает, должен ли маркер располагаться внутри или снаружи пунктов списка. Данное свойство может принимать два значения:
- outside - маркер располагается слева от содержимого (является значением по умолчанию)
- inside - маркер располагается внутри пункта списка вместе с содержимым
Теперь можно переписать предыдущий пример так, чтоб отступ с левой стороны был убран, но маркеры при этом не уезжали за край браузера:
Название документа - Кофе
- Чай
- Кофе
- Чай
- Кофе
- Чай
В примере к каждому пункту списка была добавлена рамка, чтобы визуально показать границы пунктов списка.
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 в 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: Анимация нескольких атрибутов
Конечно, в элементе
мы можем задавать изменения только для одного атрибута, но самих элементов мы можем определять несколько. Вот так, например: Здесь мы анимируем для атрибута для элемента
- радиус и ширину обводки.
Соответственно, во втором случае нумерованный список от тега
- :
Элементы находятся на одном расстоянии от начала текстового блока, что придает им дополнительный шарм.
Красивый маркированный список
В качестве символов можно использовать различные значения. Достаточно вписать новый код в свойство content.
HTML
CSS
ul { list-style-type: none; } ul li:before { content: "\203A "; padding-right: 6px; font-size: 16px; color: #00bf80; font-weight: bold; }Красивый нумерованный список
С помощью нумерованного списка можно как симпатично оформить блок текста на странице, так и создать удобное и понятное , как в начале этого материала.
HTML
CSS
ol { margin-left: 63px; list-style-type: none; counter-reset: li; } ol li:before { content: counter(li); counter-increment: li 1; padding: 0px 6px; margin-left: -28px; font-size: 12px; text-align: center; color: white; position: absolute; background: #00bf80; }Оформляйте свои статьи правильно, чтобы пользователь не повысил процент отказов.
С помощью HTML-тегов можно создать два типа списков, имеющих маркеры: нумерованные и маркированные . По умолчанию большинство браузеров отображает маркеры маркированных списков в виде окружности, а маркеры нумерованных в виде чисел, идущих по порядку. CSS предоставляет возможность изменения внешнего вида стандартных маркеров. Далее будут продемонстрированы примеры с различными видами маркеров, с помощью которых, вы сможете изменить внешний вид своих списков.
Изменение и удаление маркеров
Для изменения стандартного внешнего вида маркера в CSS используется свойство list-style-type , в качестве значения задается тот вид маркера, на который вы хотите заменить стандартный.
Пример, демонстрирующий некоторые виды маркеров для нумерованных списков:
CSS Свойство:
list-style-type:
Результат:
Ol#myList {
list-style-type: decimal
;
}
Кликните на любое значение свойства, чтобы увидеть результат
Для маркированных списков существует всего три вида маркеров, которые можно задать с помощью значений circle, disk и squred:
С помощью значения none можно удалить маркеры у пунктов в списке, но отступ слева при этом все равно останется:
Замена маркеров картинками
Если вам не подходит ни один из предлагаемых по умолчанию маркеров, то CSS предоставляет возможность заменить их любой картинкой, в этом вам поможет свойство list-style-image , в значении которого нужно прописать путь к выбранному изображению.
Примите во внимание тот факт, что изображение не будет автоматически масштабироваться под список и будет отображено собственным размером, поэтому придется подбирать изображение подходящее по размеру или редактировать существующее, уменьшив или увеличив его до нужного:
Отступ списка
При удалении маркеров у пунктов списка можно также удалить или уменьшить размер левого отступа, устанавливаемый браузером по умолчанию. Для полного удаления отступа нужно будет воспользоваться свойством padding-left , которое позволяет регулировать внутренний отступ:
В примере мы полностью убрали отступ с левой стороны, поэтому пункты списка теперь вплотную прилегают к краю окна браузера. И как видно из примера маркированный список отображается именно так, как и было задумано, но в нумерованном списке пропали маркеры. Причина кроется в самих маркерах - по умолчанию маркеры не являются частью содержимого пунктов списка, поэтому если убрать левый отступ они не сдвигаются вместе с содержимым элементов