Разбираемся, как рисовать SVG-иконки на канвасе. Придумываем способ единообразно использовать одни и те же SVG-файлы из UI-кита как в DOM, так и на канвасе.
В нашем приложении Focus Calendar для производительной отрисовки событий календаря мы используем Canvas 2D API. Помимо этого у нас есть и «обычные» интерфейсы, написанные на React.
Также у нас есть и библиотека UI-компонентов, которую мы успешно использовали в Реакт-частях интерфейса.
И вот, наконец, возникла потребность отрисовывать SVG-иконки на канвасе. При этом, конечно, хотелось брать их из UI-кита — придумать как единообразно использовать одни и те же SVG-файлы как в DOM, так и на канвасе.
В этом посте я расскажу, как мы справились с этой задачей.
Для рисования на Canvas мы используем библиотеку Konva и её React-байндинги — react-konva. Она позволяет работать с канвасом в привычной реакт-парадигме.
В документации описано несколько способов отрисовки SVG на канвасе:
Выглядит как самый прямолинейный способ, минимально увеличивающий сложность системы и подходящий для любых изображений. Чтение исходников только прибавило уверенности: используется вызов drawImage() из Canvas 2D API и никакой магии.
Любопытный способ, но, как выяснилось, Path поддерживает не все атрибуты, используемые в наших SVG-иконках. Например fill-rule="evenodd"
. Ну и первый способ по-прежнему кажется проще.
Тоже отбрасываем, т.к. мы не нашли причин его использовать, при наличии более простого способа №1.
Итак, выбираем Konva.Image. Простая демка от создателя библиотеки:
Значит, берём SVG в виде строки, конвертируем в data URI, превращаем в инстанс HTMLImageElement с помощью хука useImage
, и полученное изображение передаём в компонент Конвы <Image/>
.
Выглядит весьма просто.
Но что если нужно менять цвет этой SVG?