Самые новые браузеры — Firefox 1.5, Opera 8, а теперь еще и тестовые билды Safari стали поддерживать SVG. И меня потянуло поэкспериментировать с этим новым для меня зверем. А тут еще и случай подходящий подвернулся: я вывел в своей домашней статистике табличку посещаемости за последние 7 дней. И она мне показалась идеальным кандидатом для того, чтобы сделать к ней на SVG диаграммку.

Что получилось, обладатели Firefox 1.5 и Оперы 8 (хотя в ней может не сработать) могут видеть непосредственно на статистике внизу, а для остальных есть скриншот:

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

Как это строится

Следуя принципу разделения содержимого и представления, я решил, что строить SVG на сервере и передавать в браузер неверно. Ведь таблица с данными уже есть в содержимом, и передавать эти же данные в другом виде — это ненужное дублирование. Поэтому вся диаграмма строится Javascript'овой функцией, которая принимает название таблички, считывает данные и в DOM'е строит svg-элементы.

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

Впечатления

Это первый раз, когда я серьезно сунулся в SVG, поэтому естественно, что многие вещи я делал неправильно и неэффективно. Красноречиво об этом свидетельствует код функции, который выглядит как угодно, только не "читаемо" :-). Честно сказать, я был озабочен больше скорейшим получением результата, который можно пощупать, поэтому на поиски эффективных решений (вроде аналога innerHTML) задвинул.

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

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

<radialGradient id="bg-grad" gradientUnits="userSpaceOnUse" fx="0" fy="0" r="125">
  <stop offset="0%" stop-color="white" stop-opacity="1"/>
  <stop offset="100%" stop-color="white" stop-opacity="0"/>
</radialGradient>

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

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

Другими словами, у SVG, мне кажется, довольно трудный процесс обучения. Это вам не HTML, где все интуитивно понятно. Опять таки, не помогает и то, что так как мало народу еще этим занимается, в интернете мало документации. Спецификацию читать трудно (она, в общем-то, и не для этого), а Google откликается, по большей части, статьями о том, что "а вот есть SVG, и это круто!"

Теперь о хороших впечатлениях.

Самое хорошее впечатление — оно работает! :-). Если серьезно, то SVG довольно давно всё прочат большое будущее и даже называют "убийцей Flash'а"... Но все же не за счет технологической разницы Flash сейчас выигрывает. Просто он уже есть, а SVG еще нет. Но вот теперь становится ближе.

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

Но проблемы, конечно, неизбежны :-).

Несовместимости

После того, как я отладил диаграммку в своем Firefox, решил посмотреть на то, как с ней справится Опера. Сразу не справилась, и я потратил какое-то время, чтобы оно заработало.

Но странности остались: полчаса назад смотрел на страницу — не работало, сейчас в другом виндовом профайле та же самая Опера все показывает :-/.

Сложностей было несколько.

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

document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Gradient','1.1');

Но способ этот в долгосрочной перспективе плохой, потому что даже если браузер и честно сообщает о поддержке или неподдержке фичи, это не гарантирует отсутствия ошибок в реализации, которые могут оказаться и фатальными. Честно говоря, в данном конкретном случае с градиентами, было бы в разы лучше, если бы бразуер при отсутствии поддержки сваливался бы не на сплошной черный, а указанный пользователем сплошной цвет, либо на прозрачный. Как в CSS это делает свойство "background-image".

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

Мне это аукнулось свойством "stroke-dasharray", которое задает длины штрихов и пропусков для штриховой линии. Сначала я написал:

stroke-dasharray="1px,2px"

... и Опера это не поняла. Убрал "px" — заработало. Firefox воспринимал оба варианта. В качестве интеллектуальной задачки, кому интересно, посмотрите в спецификацию свойства и скажите, какой браузер прав? Мне пока кажется, что Firefox :-).

Зато у Firefox'а есть, похоже, баг в другом месте. Чтобы подключить градиент в SVG, надо сослаться на его id через URL:

fill="url(#bg-gradient)"

Так вот, если URL самой стрницы уже содержит якорь, то Firefox градиент не находит. Вот, наример: http://softwaremaniacs.org/referers/#TotalHits. А так быть явно не должно.


А теперь есть идея все то же сделать через canvas :-). Проверим на практике обещания HTML5 быть проще.

Комментарии: 3

  1. Flack

    Спасибо, познавательно.

  2. Алексей Захлестин

    хех.. пока читал как раз и хотел предложить сделать через canvas ;-)

  3. Kildor

    а девятую оперу смотрел? ;-) Там очень много улучшений в SVG, и как минимум страница со статистикой смотрится вполне кузяво…

Добавить комментарий