SVG: Используем pattern для заполнения объектов

Сегодня мне удалось попробовать элемент pattern для создания необычной заливки SVG-объекта. Этот опыт нужно записать!

Для начала нужно создать сам паттерн в секции defs. Например так:

<pattern id="bricks"
  patternUnits="userSpaceOnUse"
  x="0" y="0" width="10" height="10">
  <rect width="10" height="10" style="fill:#DB531D"/>
  <path d="M1,0 L9,0" style="stroke:#fff;stroke-width:2"/>
</pattern>

В данном случае с помощью координат x, y, width и height мы мы определяем область рисования паттерна. После этого описываем что будет внутри. В данном случае будет коричневый прямоугольник на всю область рисования и белая черточка.

Теперь паттерн можно использовать в свойстве fill при оформлении любого объекта, например вот так:

<rect x="10" y="10"
  width="300" height="200" style="fill:url(#bricks)" />
Опубликовано в: SVG, Все записи | Помечено | Оставить комментарий

SVG: Особенности оформления фигур с помощью CSS

Сегодня я столкнулся с весьма интересными особенностями работы браузеров при отображении SVG-фигур оформленных через CSS. Для начала возьмем и создадим тестовый SVG-объект:

<rect
  id="testRect"
  x="100" y="100"
  width="300" height="100"/>

Первая часть эксперимента

Через инлайн стили зададим ему офромление. Для этого добавим параметр style

style="stroke:red;stroke-width:5"

В результате наш объект будет с красной рамкой во всех приличных браузерах. Это хорошо и ожидаемо.

Подключим к нашему SVG-документу внешний CSS. О том как подключить CSS к SVG есть специальная заметка. Ну, в общем примерно так:

<?xml-stylesheet type="text/css" href="style.css" ?>

Поместим в этот CSS селектор #testRect с соответствующими свойствами:

#testRect {
  stroke:red;
  stroke-width:5
}

Проверим в Chromium\Chrome, Firefox и Opera — работает. Это значит, что в браузерах работают как inline-стили, так и внешние.

Вторая часть эксперимента

Допустим, мы хотим сделать заливку для прямоугольника в виде простого градиента. Для этого добавим в SVG-документ в секцию defs декларацию градиента:

<linearGradient
  id="fill">
  <stop style="stop-color:#999" offset="0"/>
  <stop style="stop-color:#333" offset="1"/>
</linearGradient>

и используем её через inline-стили:

style="fill:url(#fill)"

Работает во всех браузерах. Идем дальше!
Вынесем декларацию свойства fill во внешний файл, к остальным свойствам.

#testRect {
  stroke:red;
  stroke-width:5;
  fill:url(#fill)
}

В Chrome\Chromium работает, в Firefox 12 нету градиента, в Opera 11 тоже никакого градиента.
посмотреть в песочнице

Вывод:

Обращения к элементам SVG-документа из внешней таблицы стилей (CSS) лучше оставить на будущее.

Опубликовано в: Chrome, CSS, Firefox, Opera, SVG, Все записи | Помечено , | Оставить комментарий

Автомобили ручной работы в SVG

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

Ралли по извилистой дороге
Красный автомобиль мчится по извивающейся трассе с постоянной скоростью. Использован элемент animateMotion и масштабирование изображения с помощью параметра transform. Сам автомобиль вынесен в отдельный файл и подключен с помощью элемента image.
Нормально отображается в браузерах: Chrome\Chromium, Firefox и Opera.

Кольцевые гонки двух автомобилей
Красный автомобиль едет по внутреннему кругу с постоянной скоростью. Его лихо обгоняет синий автомобиль и срезает на повороте. Авария неизбежна, подождите немного и она обязательно произойдет… или нет, не произойдет.
Что любопытно, в браузере Opera нагрузка на процессор достаточно велика, но в Firefox она просто выходит за рамки приличия. Chrome\Chromium по нагрузке держатся на уровне с Оперой, но не всегда с первого раза подгружают автомобили, поэтому иногда приходится обновлять страницу.

Разгон и торможение автомобилей
Четыре автомобиля стартуют и едут по прямой. Красный автомобиль едет с постоянной скоростью, синий медленно стартует, но потом разгоняется, зеленый стартует быстро, но в конце тормозит. Желтое авто быстро выкатывается к середине и медленно едет дальше, в конце ускоряется. Демонстрируется работа animateMotion с настройками по умолчанию и специальными настройками keySplines и keyTimes.
В Firefox этот пример не работает. Его можно заставить там работать, но тогда в Chrome\Chromium работать не будет.

Параллельная парковка
Красный автомобиль выполняет упражнение «параллельная парковка». Демонстрируются свойства fill=”freeze”, которое оставляет изображение после анимации на месте и rotate=”auto-reverse”, которое разворачивает перемещаемый объект на 180 градусов.

Ночная поездка
Синий автомобиль с включенным ближним светом едет по ночному прямоугольнику. Вместо желанных фильтров использован радиальный градиент с полной прозрачностью на stop-opacity.

Общие наблюдения:
В браузерах Firefox и Opera автомобили имеют гладкие очертания, что придает им товарный вид. В Chrome\Chromium транспортные средства явно поцарапаны чем-то напоминающим Canvas. Это явно хулиганские выходки. Если кто-нибудь подскажет как с ними бороться — я буду благодарен.

Опубликовано в: Chrome, Firefox, Opera, Presto, SVG, WebKit, Браузеры, Все записи | Оставить комментарий

SVG: Кто и как поддерживает анимацию через spline?

Оказывается в SVG можно делать не только равномерные анимации, но и анимации с переменной скоростью. Для этого нужно добавить к элементу анимации свойство calcMode, которое по умолчанию выставлено в paced (равномерная анимация). В данном случае меня интересует значение spline, которое позволяет регулировать скорость изменения анимируемого свойства. Например, начинать быстро, а заканчивать медленно. Для определения изменения скорости используются свойства keySplines и keyTimes.

Поддерживают изменение скорости все браузеры: Chrome\Chromium, Firefox и Opera. Однако поддерживают его по-разному. В спецификации сказано, что keySplines может принимать в качестве значения несколько групп по четыре числа от 0 до 1. Группы должны быть разделены точкой с запятой. Второе полезное свойство — keyTimes, которое принимает набор чисел от 0 до 1. Этих чисел должно быть на одно больше чем групп в keySplines.

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

calcMode="spline"
keySplines="0 0 1 0;0 0 1 0;0 0 1 0"
keyTimes="0;.1;.9;1"

Пробуем!
В браузерах Chrome\Chromium и Opera анимация проходит как и полагается. В Firefox анимации нет, что свидетельствует об ошибке, если верить спецификации.

Попробуем иначе — уберем keyTimes.

calcMode="spline"
keySplines="0 0 1 0"

В Firefox заработало, в Opera продолжает работать. В Chrome\Chromium тоже работает, но ускорения уже не получается.

Пока, мои попытки заставить анимацию проходить одинаково в браузерах Firefox, Chrome\Chromium и Opera не увенчались успехом. Похоже кто-то Firefox или Chrome не слишком точно следуют спецификации.
Подсказки или мысли на тему как решить эту задачку будут горячо приветствоваться.

Для подбора значений параметра keySpline есть довольно удобный инструмент.

Опубликовано в: Chrome, Firefox, Opera, SVG, WebKit, Браузеры, Все записи | Помечено , , , | Оставить комментарий

SVG: Использование подключенных ресурсов

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

<image id="rect" xlink:href="rect.svg" width="100" height="50"/>

После этого использую его пару раз:

<use xlink:href="#rect" />
<use xlink:href="#rect" y="200" />

В результате в браузере Opera отрисовывается только последнее использование, а в Firefox, Chrome\Chromium оба случая будут видны пользователю. Подозрение на баг в Опере.

Если в секции defs использовать другие элементы — они отрисовываются нормально во всех браузерах.

Опубликовано в: Opera, SVG, Браузеры, Все записи | Помечено , | 1 Комментарий

SVG: Такой странный animateMotion

Прошлым летом я уже писал про SVG-элемент animateMotion и приводил пример его работы. Вчера он преподнес мне неожиданный сюрприз. Оказывается браузеры разделились в интерпретации параметра transform анимируемого объекта. В Firefox и Chrome\Chromium трансформации применяются только к объекту и его визуально отображаемым детям, а в Opera и еще одном мобильном браузере элемент animateMotion наследует transform и соответственно модифицирует путь по которому объект будет перемещаться.

Приведу пример:

<rect width="900" height="200" fill="#000"
  transform="scale(0.1)">
  <animateMotion
    path="M10,10 L 700,100 L 10,100 Z"
    dur="10s" />
</rect>

В результате этого в Firefox\Chrome\Chromium прямоугольник будет уменьшен, но будет перемещаться на 700 пунктов вправо и т.д., а в Opera уменьшенный прямоугольник будет перемещаться только на 70 пунктов вправо.

Сделать анимацию совместимой помогает элемент use:

<defs>
  <rect id="rect" width="900" height="200"
  transform="scale(0.1)"/>
</defs>
<use xlink:href="#rect">
  <animateMotion
    path="M10,10 L 700,100 L 10,100 Z"
    dur="10s" />
</use>

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

Опубликовано в: Chrome, Firefox, Opera, Presto, SVG, WebKit, Браузеры, Все записи | Помечено , | Оставить комментарий

SVG: Кто чего поддерживает?

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

Самая удобная таблица у Opera: Как Presto 2.10 поддерживает SVG.
У Chrome\Chromium все немного беднее. Последнее обновление таблицы поддержки тегов SVG в Webkit аж в 2011 году.
У Firefox тоже есть своя таблица поддержки SVG.

Кстати, поправки и дополенения как всегда приветствуются.

Опубликовано в: Chrome, Firefox, Opera, Presto, SVG, WebKit, Браузеры, Все записи | 2 Комментариев

SVG: Анимация и её события

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

Всего в стандарте SVG описано три события: beginEvent (срабатывает в момент начала анимации), endEvent (срабатывает в конце процесса анимации), repeatEvent (отправляется каждый раз, когда начинается новый анимационный цикл).

В теории всё это очень красиво, а как обстоит дело на практике? В результате моих экспериментов получается следующая картина: ни один из доступных мне браузеров не бросил событие при декларации анимационного элемента в SVG-документе. При динамическом создании анимационных элементов события бросают Opera 11.62 и Firefox 11 под Ubuntu. Те же браузеры замечательно делают все это под Windows.

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

var newElement = document.createElementNS(SVGNS, 'rect');
newElement.setAttribute("width","200");
newElement.setAttribute("y","200");
newElement.setAttribute("height","100");
var animate = document.createElementNS(SVGNS, 'animate');
animate.setAttribute("attributeType","XML");
animate.setAttribute("attributeName","x");
animate.setAttribute("attributeName","x");
animate.setAttribute("from","200");
animate.setAttribute("to","600");
animate.setAttribute("dur","5s");
animate.setAttribute("repeatCount","indefinite");
animate.addEventListener("beginEvent", function() {
    alert("Go!");
}, false);
newElement.appendChild(animate);
ROOT.appendChild(newElement);

Если найдется человек, который сможет поймать эти события в Chrome — буду очень рад услышать историю успеха.

Опубликовано в: Firefox, Opera, Браузеры, Все записи | Помечено , , | Оставить комментарий

Школа весеннего программирования

Сегодня, 21 апреля представители компании Motorola Mobility рассказывали в «Весенней школе программирования» о том как можно использовать JavaScript и SVG для отображения мультимедийной информации на телевизионных приставках.

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

В основном я рассказывал все то, о чем пишу в этом блоге. Про работу с SVG-файлами и рисование простейших элементов типа эллипса. Затронул тему градиентов и анимации элементов SVG. Кроме того, речь шла о работе с DOM SVG с помощью простого JavaScript. Например, как подключить JavaScript в SVG-файл, как создать новый элемент в DOM-дереве. Рассказал и о элементе video. Ну и в заключение рассмотрел фреймворк RaphaelJS, описал его достоинства, показал симпатичные демки и маленький пример работы.

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

Резюме:
Мероприятие удалось! А из многих слушателей школы могут получиться очень хорошие front-end разработчики.

Для себя я сделаю такой вывод:
В будущем нужно уделять внимание «вау» эффектам т.к. именно они вызывают огонь в глазах и желание узнать больше.

Опубликовано в: Все записи, Мероприятия | Оставить комментарий

Хороший обзор трех библиотек: RaphaelJS, PaperJS и ProcessingJS

Сегодня я прочитал интересную статью-сравнение трех графических библиотек: RaphaelJS, PaperJS и ProcessingJS. Резюме примерно следующее:
RaphaelJS — SVG-ориентированная библиотека, которая поддерживает даже старые версии Internet Explorer. Удобна для работы с интерактивными рисунками.
PaperJS — Canvas-ориентированная библиотека, которая тоже весьма удобна для интерактивных графических приложений.
ProcessingJS — быстрая Canvas-ориентированная библиотека для неинтерактивных проектов.

Опубликовано в: JavaScript, JS-библиотека, Все записи | Помечено , , | Оставить комментарий