Структура и представление

Автор: Евгений Рыжков и Тимур Лисица Дата публикации: 27.11.2010

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

Одна из целей XML — предоставить доступ к структуре данных и отделить эту структуру от ее визуального представления. Рассматривая SVG-код для рисунка кота в «Создание SVG графики», можно было догадаться по структуре кода, что это кот — об этом говорит расположение и размер геометрических фигур, которые формируют рисунок. Если бы нужно было сделать структурные изменения, например, уменьшить усы, округлить нос, или сделать уши длиннее с закругленными кончиками — получим изображение кролика. И не имеет значения, какой была основа представления. Таким образом, структура подсказывает Вам, что собой представляет графика.

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

структура против представления

Использование стилей с SVG

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

Встроенные стили

В следующем примере использованы встроенные стили. Это именно тот способ, который мы использовали во всех предыдущих примерах: атрибуту style задавали серию визуальных свойств со значениями:

<circle cx="20" cy="20" r="10" style="stroke: black; stroke-width: 1.5; fill: blue; fill-opacity: 0.6" />

Внутренние таблицы стилей

Вообще нет необходимость вставлять стили в каждый элемент SVG, тем самым захламляя код. Можно создать внутренние таблицы стилей для сохранения часто используемых стилей, которые можно применить для всех элементов определенного типа или применить только к элементам, содержащих определенный класс. В следующем примере установлена внутренняя таблица стилей, на основе которой все круги будут создаваться с утолщенной пунктирной линией и светло желтой заливкой. Таблицу стилей помещена в элемент <defs>, который мы обсудим немного позже. На примере будет нарисовано несколько кругов. Два последних будут использовать inline стили, корректирующие оформление, заданное внутренней таблицей стилей:

<svg width="200px" height="200px" viewBox="0 0 200 200">
<defs>
	<style type="text/css"><![CDATA[
	circle {
	fill: #ffc;
	stroke: blue;
	stroke-width: 2;
	stroke-dasharray: 5 3
	}
	]]></style>
</defs>
<circle cx="20" cy="20" r="10" />
<circle cx="60" cy="20" r="15" />
<circle cx="20" cy="60" r="10" style="fill: #cfc" />
<circle cx="60" cy="60" r="15" style="stroke-width: 1; stroke-dasharray: none;" />
</svg>
пример использования внутренних таблиц стилей

Внешние таблицы стилей

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

Вот тут-то и пригодятся внешние таблицы стилей — все содержимое элемента <style> (включая <! CDATA[ и ]]>) сохраняем во внешнем файле, который и станет внешней таблицей стилей. Следующий пример демонстрирует содержимое такой внешней таблице с именем ext_style.css. Эта таблица использует множество селекторов, включая *, который указывает на все элементы:

* { fill:none; stroke: black; } /* по умолчанию для всех элментов */
rect { stroke-dasharray: 7 3; }
circle.yellow { fill: yellow; }
.thick { stroke-width: 5; }
.semiblue { fill:blue; fill-opacity: 0.5; }

Внешняя таблица готова. Теперь посмотрим как ее подключить к SVG-документу:

<?xml version="1.0"?>
<?xml-stylesheet href="ext_style.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="200px" height="200px" viewBox="0 0 200 200" preserveAspectRatio="xMinYMin meet">
<line x1="10" y1="10" x2="40" y2="10" />
<rect x="10" y="20" width="40" height="30" />
<circle class="yellow" cx="70" cy="20" r="10" />
<polygon class="thick" points="60 50, 60 80, 90 80" />
<polygon class="thick semiblue" points="100 30, 150 30, 150 50, 130 50" />
</svg>

Результат смотрим в «живую» или на картинке ниже:

пример использования внешней таблицы стилей

Заметка

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

Атрибуты представления

Подавляющее большинство Ваших SVG-документов будут использовать стили для оформления, но не помешает знать, что SVG позволяет также задавать оформление и атрибутами представления. Например, вместо:

<circle cx="10" cy="10" r="5" style="fill: red; stroke:black; stroke-width: 2;" />

можно написать так:

<circle cx="10" cy="10" r="5" fill="red" stroke="black" stroke-width="2" />

Такая запись может показаться смесью структуры и представления. И тут вы абсолютно правы. И даже следует подумать: а какой от этого толк? А толк вот в чем: атрибуты представления могут пригодиться, когда Вы будете создавать документы SVG конвертируя данные из XML-источника в SVG (об этом детальней в последующих главах). В данном случае будет проще создать отдельные атрибуты, чем содержимое атрибута style. Атрибуты представления также могут пригодится в случаях когда отсутствует поддержка таблиц стилей.

Атрибуты представления имеют самый низкий приоритет среди способов задать оформление. Любое определение, исходящая от встроенных стилей, внутренних или внешних таблиц стилей будет «перекрывать» атрибут представления. В следующем примере круг будет залит красным, а не зеленым цветом.

<svg width="200" height="200">
<defs>
<style type="text/css"><![CDATA[
circle { fill: red; }
]]></style>
</defs>
<circle cx="20" cy="20" r="15" fill="green" />
</svg>

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

Куда дальше