Группирование и привязка SVG объектов
Дата публикации: 07.12.2010
Большинство не абстрактных изображений состоит из групп фигур и линий, которые формируют узнаваемые объекты. Подобные группы элементов SVG позволяет объединить чтобы сделать код более понятным, структурированным и удобным.
Элемент <g>
Элемент <g> объединяет все дочерние элементы в группу. Зачастую имеет уникальный id. Так же может в себе содержать <title> и <desc> чтобы улучшить доступность для невизуальных браузеров. В дополнение к этому, <g> обеспечивает удобство и сокращение объема кода при использовании стилей: заданный стиль для <g> будет распространятся на все дочерние элементы. В следующем примере избежим дублирования style=»fill:none; stroke:black;» для элементов рисунка:
<svg width="240px" height="240px" viewBox="0 0 240 240"> <title>Рисунок группами</title> <desc>Рисунок дома и людей</desc> <g id="house" style="fill: none; stroke: black;"> <desc>Дос с дверью</desc> <rect x="6" y="50" width="60" height="60"/> <polyline points="6 50, 36 9, 66 50"/> <polyline points="36 110, 36 80, 50 80, 50 110"/> </g> <g id="man" style="fill: none; stroke: black;"> <desc>Мужик</desc> <circle cx="85" cy="56" r="10"/> <line x1="85" y1="66" x2="85" y2="80"/> <polyline points="76 104, 85 80, 94 104" /> <polyline points="76 70, 85 76, 94 70" /> </g> <g id="woman" style="fill: none; stroke: black;"> <desc>Тетка</desc> <circle cx="110" cy="56" r="10"/> <polyline points="110 66, 110 80, 100 90, 120 90, 110 80"/> <line x1="104" y1="104" x2="108" y2="90"/> <line x1="112" y1="90" x2="116" y2="104"/> <polyline points="101 70, 110 76, 119 70" /> </g> </svg>

Допускается вложенность группы элементов в другую группу.
Элемент <g> по своей сущности очень напоминает группирование слоев в Adobe Photoshop и Adobe Illustrator.
Элемент <use>
Часто в дизайне встречаются повторяющиеся элементы. Например, рекламный буклет может содержать логотип компании в верхнем левом и нижнем правом углу каждой страницы. В каком-нибудь Adobe Illustrator достаточно один раз нарисовать логотип, сгруппировать все его составляющие, скопировать сгруппированный рисунок и вставлять его сколько угодно раз в нужные места. Элемент <use> предоставляет аналог функции копи-паста для группы элементов, объединенных с помощью <g>.
Чтобы скопировать-вставить определенную группу (она должна иметь id), добавляем элемент <use>, указываем какую группу будем копировать (атрибут xlink:href) и задаем положение копии (относительно положения оригинала). Возьмем предыдущий пример и сделаем копии дома и людей:
... <use xlink:href="#house" x="70" y="100"/> <use xlink:href="#woman" x="-80" y="100"/> <use xlink:href="#man" x="-30" y="100"/>

Элемент <defs>
В предыдущем примере сложно не заметить недостатки:
- нужно знать позицию оригинала и отталкиваться от него, а не просто указать нужные координаты;
- цвета, а точнее все стили, у копий будут таким же как и у оригинала: их нельзя изменить с помощью <use>;
- при использовании <g> отобразится все сгруппированные элементы. В нашем примере нельзя определить, сгруппировать и «сохранить» все три элемента, а отобразить только, например, дом или мужчину.
Элемент <defs> позволяет решить эти проблемы. Заключаем сгруппированные объекты в <defs> — определяем элементы без их отображения. Спецификация SVG рекомендует группы, которые будут повторно использоваться, заключать в <defs>, чтобы код получился более гибким и компактным. В следующем примере дом, мужчина и женщина определены так, чтобы их верхний левый угол находился в (0, 0) и не был указан цвет заливки. Так как группы находятся внутри <defs>, они не будут отображаться на экране, но будут служить в качестве «шаблонов» для использования в будущем. Добавим еще одну группу couple, которая, использует <use> для групп man и woman. Заметьте, что нижний рисунок не может использовать couple, потому что поменяли местами женщину и мужчину:
<svg width="240px" height="240px" viewBox="0 0 240 240"> <title>Рисуем группами</title> <desc>На рисунке дом и люди</desc> <defs> <g id="house" style="stroke: black;"> <desc>Дом с дверью</desc> <rect x="0" y="41" width="60" height="60" /> <polyline points="0 41, 30 0, 60 41" /> <polyline points="30 101, 30 71, 44 71, 44 101" /> </g> <g id="man" style="fill: none; stroke: black;"> <desc>Мужик</desc> <circle cx="10" cy="10" r="10" /> <line x1="10" y1="20" x2="10" y2="44" /> <polyline points="1 58, 10 44, 19 58" /> <polyline points="1 24, 10 30, 19 24" /> </g> <g id="woman" style="fill: none; stroke: black;"> <desc>Тетка</desc> <circle cx="10" cy="10" r="10" /> <polyline points="10 20, 10 34, 0 44, 20 44, 10 34" /> <line x1="4" y1="58" x2="8" y2="44" /> <line x1="12" y1="44" x2="16" y2="58" /> <polyline points="1 24, 10 30, 19 24" /> </g> <g id="couple"> <desc>Мужик и тетка</desc> <use xlink:href="#man" x="0" y="0" /> <use xlink:href="#woman" x="25" y="0" /> </g> </defs> <!-- используем определенные ранее группы --> <use xlink:href="#house" x="0" y="0" style="fill: #cfc;" /> <use xlink:href="#couple" x="70" y="40" /> <use xlink:href="#house" x="120" y="0" style="fill: #99f;" /> <use xlink:href="#couple" x="190" y="40" /> <use xlink:href="#woman" x="0" y="145" /> <use xlink:href="#man" x="25" y="145" /> <use xlink:href="#house" x="65" y="105" style="fill: #c00;" /> </svg>

Элемент <use> не ограничен рамками одного SVG документа: атрибут xlink:href может сослаться на любой подходящий файл или адрес в Сети. Это позволяет собрать несколько общих элементов в один SVG файл и использовать в качестве «донора». Например, создаем identity.svg, в котором соберем графику, использующуюся организацией:
<g id="company_mascot"> <!-- талисман компании --> </g> <g id="company_logo" style="stroke: none;"> <polygon points="0 20, 20 0, 40 20, 20 40" style="fill: #696;" /> <rect x="7" y="7" width="26" height="26" style="fill: #c9c;" /> </g> <g id="partner_logo"> <!-- логотип партнера --> </g>
и затем ссылаемся на него:
<use xlink:href="identity.svg#company_logo" x="200" y="200" />
Элемент <symbol>
Элемент <symbol> позволяет группировать элементы еще одним способом. В отличии от элемента <g>, <symbol> никогда не отображается: нет необходимости его скрывать с помощью <defs>.
Еще одна особенность <symbol> — это возможность использования атрибутов viewBox и preserveAspectRation, чтобы изображение смогло вписаться в окно просмотра, установленное элементом <use>. В следующем примере видим, что width и height для простой группы игнорируются (для верхних двух прямоугольников), но они используются при отображении <symbol>. Края правого нижнего прямоугольника на обрезаны, потому что для preserveAspectRation задано slice.
<svg width="240px" height="240px" viewBox="0 0 240 240"> <title>Symbols vs groups</title> <desc>Use</desc> <defs> <g id="octagon" style="stroke: black;"> <desc>Octagon as group</desc> <polygon points="36 25, 25 36, 11 36, 0 25,0 11, 11 0, 25 0, 36 11"/> </g> <symbol id="sym-octagon" style="stroke: black;" preserveAspectRatio="xMidYMid slice" viewBox="0 0 40 40"> <desc>Octagon as symbol</desc> <polygon points="36 25, 25 36, 11 36, 0 25,0 11, 11 0, 25 0, 36 11"/> </symbol> </defs> <use xlink:href="#octagon" x="40" y="40" width="30" height="30" style="fill: #c00;"/> <use xlink:href="#octagon" x="80" y="40" width="40" height="60" style="fill: #cc0;"/> <use xlink:href="#sym-octagon" x="40" y="80" width="30" height="30" style="fill: #cfc;"/> <use xlink:href="#sym-octagon" x="80" y="80" width="40" height="60" style="fill: #699;"/> </svg>

Элемент <image>
Если <use> позволяет повторно использовать часть SVG файла, то элемент <image> содержит или SVG файл целиком, или растровый файл (JPEG или PNG). Если использоваться будет SVG файл — атрибуты x, y, width и height устанавливают окно просмотра, в котором будет отображаться содержимое этого файла. Если растровый файл — он будет масштабироваться чтобы соответствовать прямоугольнику, определенному атрибутами. Пример внедрения растрового изображения:
<svg width="310px" height="310px" viewBox="0 0 310 310"> <!--эмулируем тень для эллипса--> <ellipse cx="154" cy="154" rx="150" ry="120" style="fill: #999999;&quo;/> <!--основная фигура эллипса--> <ellipse cx="152" cy="152" rx="150" ry="120" style="fill: #cceeff;"/> <!-- внедряем картинку: xlink:href - ссылка на растровое изображение; x и y - положение врхнего левого угла image --> <!-- width и height - размеры image, под которые будет подгонятся реальное изображение --> <image xlink:href="kwanghwamun.jpg" x="72" y="92" width="160" height="120"/> </svg>

Куда дальше
- следующая — Трансформация в SVG: перемещение
- предыдущая — Структура SVG документа и представление
- содержание