Учитывая, что одной из распространенных целей SVG является создание диаграмм и иллюстраций, вполне логично, что завершение линий и путей стрелками — очень распространенный запрос. Хотя можно украсить линию собственной индивидуальной формой стрелки, закодированной вручную, гораздо эффективнее создать шаблон стрелки с помощью элемента <marker>.
Вы можете добавить стрелку к элементам line, polyline, polygon и path.
Форма стрелки определяется в элементе маркера, который размещается внутри <defs> в начале вашего SVG:
1 2 3 4 5 6 7 8 9 10 |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 100"> <defs> <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="0" refY="3.5" orient="auto"> <polygon points="0 0, 10 3.5, 0 7" /> </marker> </defs> <line x1="0" y1="50" x2="250" y2="50" stroke="#000" stroke-width="8" marker-end="url(#arrowhead)" /> </svg> |
Результат:
В принципе, любую форму, линию или набор элементов можно нарисовать внутри этого пространства в виде стрелки. В данном случае фигура представляет собой треугольник, который касается верхнего левого и нижнего левого углов области маркера, а точка касается крайней правой стороны. <line>, в нижней части SVG ссылается на этот маркер через его <id>.
Атрибуты refX и refY позиционируют маркер относительно конца пути.
Установка этих значений на 0 (по умолчанию) поместит верхний левый угол <marker> на конец строки.
В случае сплошной стрелки значения конечной стрелки будут равны 0 для положения X и половине высоты маркера для положения Y.
Установка ориентации на автоматическое выравнивание стрелки orient=”auto” по направлению пути.
Мы можем увидеть эффект этого, если изменим начальную или конечную точку линии, чтобы линия была не горизонтальна.
1 2 3 |
<line x1="0" y1="0" x2="250" y2="50" stroke="#000" stroke-width="8" marker-end="url(#arrowhead)" /> |
Параметр “auto” выравнивает маркер вдоль пути.
Например: orient=”22″
После того как маркер определен, его можно использовать повторно столько раз, сколько пожелаете. Очевидным применением является создание путей или линий с двунаправленными стрелками с использованием marker-start и marker-end.
Однако если вы примените один и тот же элемент <marker> к обоим концам, они оба будут указывать в одном направлении:
1 2 3 4 5 6 7 8 9 10 |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 100"> <defs> <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="0" refY="3.5" orient="auto"> <polygon points="0 0, 10 3.5, 0 7" /> </marker> </defs> <line x1="0" y1="50" x2="250" y2="50" stroke="#000" stroke-width="8" marker-end="url(#arrowhead)" marker-start="url(#arrowhead)" /> </svg> |
Лучшим подходом будет создание двух отдельных стрелок, ссылающихся на них по отдельности:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350 100"> <defs> <marker id="startarrow" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto"> <polygon points="10 0, 10 7, 0 3.5" fill="red" /> </marker> <marker id="endarrow" markerWidth="10" markerHeight="7" refX="0" refY="3.5" orient="auto" markerUnits="strokeWidth"> <polygon points="0 0, 10 3.5, 0 7" fill="red" /> </marker> </defs> <line x1="100" y1="50" x2="250" y2="50" stroke="#000" stroke-width="8" marker-end="url(#endarrow)" marker-start="url(#startarrow)" /> |
Что создает:
В принципе, должна быть возможность создать одиночный <symbol>, который преобразуется в стрелку с соответствующей ориентацией для любого конца строки. Это немного сложнее, чем может показаться на первый взгляд, поэтому я оставлю эту технику для следующей статьи.
Все примеры до сих пор были адаптивными, что означает, что и стрелка(и), и толщина линии будут изменяться в зависимости от ширины области просмотра (viewport). В некоторых случаях вам может понадобиться, чтобы линия и стрелки меняли размер, но не толщину, обычно на практике они остаются в виде тонких линий.
Этот пример создан из следующего кода:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 200"> <defs> <style> path, polyline { fill: none; stroke: #231F20; vector-effect: non-scaling-stroke; stroke-width: 2; } path { stroke-dasharray: 11, 5; } </style> <marker id="pointer" markerWidth="10" markerHeight="8" refX="9.5" refY="5.1" orient="-45" markerUnits="userSpaceOnUse"> <polyline points="1 1, 9 5, 1 7" /> </marker> </defs> <path d="M16.7,178 c87.6-46.9,162.9-185.4,227-136.4C307.2,90.1,195,158.5,111,108.9C71,85.2,92.2,30.7,126,7" marker-end="url(#pointer)"/> </svg> |
В данном случае стрелка является элементом <polyline>. Маркеры не могут наследовать обводку или заливку элемента, к которому они прикреплены, но им легко придать одинаковый внешний вид с помощью сгруппированного комбинатора в таблице стилей, как показано выше.
Значением по умолчанию для атрибута MarkerUnits является StrokeWidth (по этой причине он не применяется в приведенных выше примерах). Он определяет систему координат для маркера: по сути, масштаб стрелки относительно пути. strokeWidth связывает размер маркера с обводкой пути; userSpaceOnUse использует текущую систему координат.
Использование этого в сочетании с vector-effect: non-scaling-stroke эффективно создает линию пути и стрелку при любом размере браузера; в этом случае я также манипулировал значениями refX, refY и orient, чтобы «закрепить» стрелку polyline на пути и придать ей более эстетичное направление.
Хотя создание маркеров в первый раз может оказаться немного сложной задачей, их адаптируемость и возможности повторного использования делают их идеальными для иллюстраций. Есть и другие варианты использования маркеров, включая украшение самого контура; Оставлю это для следующей статьи.
Фотография Julien Belli, использована под лицензией Creative Commons Attribution 2.0 Generic.
Перевод статьи: Making Arrows in SVG@dudleystorey