Печатает... Список заметок

Управляем масштабированием обводки SVG при помощи vector-effect

Интро

vector-effect — атрибут, позволяющий управлять отрисовкой векторного объекта. Также может быть применён к объекту как CSS-свойство.

Векторный эффект действует на следующие десять объектов (во всяком случае по документации):

  • <circle>,
  • <ellipse>,
  • <foreignObject>,
  • <image>,
  • <line>,
  • <path>,
  • <polygon>,
  • <polyline>,
  • <rect>,
  • <text>,
  • <textPath>
  • <tspan>,
  • <use>

Сейчас существует пять возможных значений:

  • none (по умолчанию),
  • non-scaling-stroke,
  • non-scaling-size,
  • non-rotation,
  • fixed-position.

Сперва я думал разобраться в особенностях применения каждого из свойств, но позже прочёл что последние три рискуют быть исключёнными из спецификации из-за отсутствия реализаций. Поэтому далее поговорю о практическом применении non-scaling-stroke.

Практическое применение vector-effect: non-scaling-stroke

Задача: вставить SVG-иконку в блок с вариативными размерами.

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

Следующим этапом я попробую указать толщину обводки для иконок. Пусть это будут восемь пикселей для большой, четыре для средней и два для малой.

Обращаем внимание на то, что обводка в средней и малой иконках явно тоньше назначенной. Почему?

Всё дело в том что иконка имеет viewbox 192 × 192 пикселя, это указано в соответствующем атрибуте, а далее мы масштабируем её и по-умолчанию толщина обводки также масштабируется.

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

Чтобы отключить масштабирование обводки применяем к нашим SVG свойство vector-effect: non-scaling-stroke

Если вы заглянете в исходный код, то обратите внимание, что в первых двух примерах я переиспользовал <path> при помощи <use>, а в последнем трижды копировал один и тот же код. Всё дело в том, что несмотря на указание в документации о том что vector-effect должен применяться к <use> у меня он это делать отказывался.

Бонус

Обратите внимание, что в первых двух примерах края и углы контуров острые, а в последнем уголочки мягкие. Скруглить углы мне помогли два свойства: stroke-linecap и stroke-linejoin, первое управляет формой открытых окончаний путей, второе формой углов. Значение round скруглило концы и углы.

Пример на кодпене