Редактируемая система SVG-иконок

Простой пример

Существуют множество способов создания системы SVG-иконок (SVG Icon System), но один из методов, который использует возможности Vue, — это создание редактируемых встроенных иконок в виде компонентов. Некоторые из преимуществ такого подхода:

Сначала мы создадим каталог для всех иконок и назовём их в стандартизированном подходе для облегчения их поиска:

components/icons/IconBox.vue
components/icons/IconCalendar.vue
components/icons/IconEnvelope.vue

Вот репозиторий с примером для начала работы, где вы увидите готовую настройку: https://github.com/sdras/vue-sample-svg-icons/

Сайт документации

Мы создадим компонент базовой иконки (IconBase.vue), который использует слот.

<template>
<svg xmlns="http://www.w3.org/2000/svg"
:width="width"
:height="height"
viewBox="0 0 18 18"
:aria-labelledby="iconName"
role="presentation"
>
<title
:id="iconName"
lang="en"
>{{iconName}} icon</title>
<g :fill="iconColor">
<slot />
</g>
</svg>
</template>

Вы можете использовать эту базовую иконку как есть, однако вам нужно обновить viewBox в зависимости от viewBox ваших иконок. В базовом компоненте мы устанавливаем width, height, iconColor и имя иконки как входные данные так, что он может динамически обновляться. Имя используется как для содержимого <title>, так и для его id для лучшей доступности.

Наш скрипт будет выглядеть следующим образом: у нас будут некоторые значения по умолчанию, поэтому иконка будет отрисовываться всегда одинаково, пока мы не изменим её:

export default {
props: {
iconName: {
type: String,
default: 'box'
},
width: {
type: [Number, String],
default: 18
},
height: {
type: [Number, String],
default: 18
},
iconColor: {
type: String,
default: 'currentColor'
}
}
}

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

Мы можем использовать его следующим образом, с единственным содержимым IconWrite.vue, содержащим пути внутри иконок:

<icon-base icon-name="write"><icon-write /></icon-base>

Теперь, если мы захотим несколько иконок с различными размерами, это сделать довольно просто:

<p>
<!-- вы можете передать меньшую `width` и `height` во входные данные -->
<icon-base
width="12"
height="12"
icon-name="write"
><icon-write /></icon-base>
<!-- или вы можете использовать значение по умолчанию, которое равно 18 -->
<icon-base icon-name="write"><icon-write /></icon-base>
<!-- или также сделать её немного больше :) -->
<icon-base
width="30"
height="30"
icon-name="write"
><icon-write /></icon-base>
</p>

Анимируемые иконки

Хранение иконок в компонентах очень удобно, когда вы хотите их анимировать, особенно при взаимодействии. Встроенные SVG-иконки имеют самую высокую поддержку для какого-либо взаимодействия. Ниже очень простой пример иконки, которая анимируется при клике:

<template>
<svg
@click="startScissors"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 100 100"
width="100"
height="100"
aria-labelledby="scissors"
role="presentation"
>
<title
id="scissors"
lang="en"
>Анимированная иконка с ножницами</title>
<path
id="bk"
fill="#fff"
d="M0 0h100v100H0z"/>
<g ref="leftscissor">
<path d="M..."/>
...
</g>
<g ref="rightscissor">
<path d="M..."/>
...
</g>
</svg>
</template>
import { TweenMax, Sine } from 'gsap'

export default {
methods: {
startScissors() {
this.scissorAnim(this.$refs.rightscissor, 30)
this.scissorAnim(this.$refs.leftscissor, -30)
},
scissorAnim(el, rot) {
TweenMax.to(el, 0.25, {
rotation: rot,
repeat: 3,
yoyo: true,
svgOrigin: '50 45',
ease: Sine.easeInOut
})
}
}
}

Мы применяем refs для группы путей, которые нам нужно переместить, и по мере того, как обе стороны ножниц должны перемещаться вместе, мы создаём функцию, которую повторно используем при обращении к refs. Использование GreenSock помогает разрешить поддержку анимации и проблемы с transform-origin во всех браузерах.

Смотрите Pen Editable SVG Icon System: Animated icon by Vue (@Vue) на сайте CodePen.



Довольно легко сделано! И легко обновлять “на лету”.

Вы можете посмотреть больше анимационных примеров в репозитории

Дополнительные замечания

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

Когда не следует этого делать

Эта система SVG-иконок действительно полезна, когда у вас есть несколько иконок, которые используются по-разному на всём сайте. Если вы дублируете одну и ту же иконку много раз на одной странице (например, во всех строках гигантской таблицы в качестве иконки удаления), может имеет больше смысла сделать спрайты, скомпилированные в лист спрайта, и использовать теги <use> для их загрузки.

Альтернативные варианты

Другие инструменты для помощи в управлении SVG-иконками включают:

Эти инструменты собирают SVG-иконки во время компиляции, что делает их сложнее для редактирования во время выполнения, потому что теги <use> могут иметь странные проблемы с кроссбраузерностью при выполнении чего-то сложного. Они также оставляют вас с двумя вложенными свойствами viewBox и, таким образом, с двумя системами координат. Это делает реализацию немного более сложной.