JavaScript API для динамического создания изображений в сочетании с CSS
Для будущих студентов курса "JavaScript Developer. Professional" подготовили перевод материала.
Также приглашаем посетить открытый вебинар на тему «Vue 3 — возможности новой версии одного из самых популярных фронтенд фреймворков». На занятии участники вместе с экспертом:
— рассмотрят ключевые отличия в синтаксисе vue2 от vue3;
— разберут, как работать с vue-router и VueX в новой версии фреймворка;
— попробуют создать проект на Vue 3 с нуля с помощью Vue-cli.
Присоединяйтесь!
![](https://habrastorage.org/getpro/habr/upload_files/b7a/62d/425/b7a62d42529858ea949e1b71ff70cc90.png)
Картинки вносят колорит в приложения. Однако, как мы все знаем, наличие большого количества изображений высокого разрешения влияет на время загрузки страницы. Для иллюстраций продуктов, сценариев и так далее, у нас нет другого выбора, кроме как добавить эти изображения и оптимизировать приложение путем их кэширования. Но если вам нужно геометрическое изображение в приложении, тогда не потребуется включать его в качестве дополнительного ресурса.
Вы можете программно генерировать геометрические изображения «на лету», используя API CSS Painting.
Давайте выясним, что это за API и как сгенерировать изображение с его помощью.
Введение в API CSS Painting
CSS Painting API позволяет разработчикам писать JavaScript-функции для отрисовки изображений в свойствах CSS, таких как background-image и border-image. Он предоставляет набор API, который дает разработчикам доступ к CSSOM. Это часть CSS Houdini (Houdini — коллекция новых API браузера, предоставляющая разработчикам доступ к самому CSS на более низком уровне).
Традиционный подход к добавлению изображения следующий:
div {
background-image: url('assets/background.jpg);
}
С помощью CSS Painting API можно вызвать функцию paint()
и передать ей ворклет (worklet), который написан с помощью JS, вместо вышеуказанного способа.
div {
background-image: paint(background);
}
В этом случае рабочий процесс будет выглядеть следующим образом.
![](https://habrastorage.org/getpro/habr/upload_files/648/30f/63d/64830f63d9f9cbcf5ddd8cf2011d0e4f.png)
Возможно, вы столкнулись с неизвестными терминами в вышеуказанном разделе. Например, что это за worklets, о которых мы продолжаем говорить?
Вкратце, JavaScript-код, написанный для программной генерации изображения, называется Paint Worklet (Рабочий пакет для рисования). Worklet — это точка расширения в канале рендеринга браузера. Есть и другие типы ворклетов (worklets), помимо worklets для рисования, например, worklets анимации, макетирования и т.д.
Теперь давайте рассмотрим пошаговый подход к программной генерации изображения.
Использование API CSS Painting на практике
В этой статье мы рассмотрим, как создать пузырьковый фон.
Шаг 1: Добавить функцию paint()
в CSS
Прежде всего, вам нужно добавить функцию paint()
в свойство CSS, на котором должно быть изображение.
.bubble-background {
width: 400px;
height: 400px;
background-image: paint(bubble);
}
bubble будет worklet, который мы создадим для генерации изображений. Это будет сделано в следующих нескольких шагах.
Совет: поделитесь своими многократно используемыми компонентами между проектами, используя Bit (Github).
Bit упрощает совместное использование, документирование и повторное использование независимых компонентов между проектами. Используйте его, чтобы максимизировать повторное использование кода, сохранить единый дизайн, ускорить доставку и построить приложения, которые будут расширяться.
Bit поддерживает Node, TypeScript, React, Vue, Angular и многое другое.
![](https://habrastorage.org/getpro/habr/upload_files/19c/3f1/57b/19c3f157bc44a35ac6d5a0e51d33affa.png)
Анимация. Пример: исследование компонентов React многоразового использования, совместно используемых на Bit.dev.
Шаг 2: Создание ворклета (worklet)
Ворклеты (worklets) должны храниться во внешнем JS-файле. Ворклет для рисования (paint worklet) будет class
. Например: - class Bubble { …. }
. Этот ворклет (worklet) необходимо зарегистрировать с помощью метода registerPaint()
.
class Bubble {
paint(context, canvas, properties) {
........
}
}
registerPaint('bubble', Bubble);
Первым параметром метода registerPaint()
должна быть ссылка, которую вы включили в CSS.
Теперь нарисуем фон.
class Bubble {
paint(context, canvas, properties) {
const circleSize = 10;
const bodyWidth = canvas.width;
const bodyHeight = canvas.height;
const maxX = Math.floor(bodyWidth / circleSize);
const maxY = Math.floor(bodyHeight / circleSize);
for (let y = 0; y < maxY; y++) {
for (let x = 0; x < maxX; x++) {
context.fillStyle = '#eee';
context.beginPath();
context.arc(x * circleSize * 2 + circleSize, y * circleSize * 2 + circleSize, circleSize, 0, 2 * Math.PI, true);
context.closePath();
context.fill();
}
}
}
}
registerPaint('bubble', Bubble);
Логика создания изображения находится внутри метода paint()
. Вам понадобится немного знаний о создании холста, чтобы рисовать изображения, как описано выше. Обратитесь к документации по Canvas API, если вы не знакомы с ним.
Шаг 3: Запустите ворклет (worklet)
Последним шагом будет запуск ворклета (worklet) в HTML-файле.
<div class="bubble-background"></div>
<script>
CSS.paintWorklet.addModule('https://codepen.io/viduni94/pen/ZEpgMja.js');
</script>
Готово!
Вы программно сгенерировали изображение всего за 3 шага.
Сгенерированное изображение
Результат того, что мы создали, будет выглядеть следующим образом.
![](https://habrastorage.org/getpro/habr/upload_files/68c/0ea/32d/68c0ea32d40d560e8ea9f4ad621358f5.png)
View in Editor (просмотр в редакторе)
Что еще мы можем сделать с помощью этого API CSS Painting?
Возможности CSS Painting API еще не исчерпаны. Есть другие вещи, которые вы можете с ним сделать.
1. Вы можете создавать динамические изображения
Например, можно динамически изменять цвет пузырьков. Для этого применяются переменные CSS. Чтобы применить CSS-переменные, браузер должен заранее знать, что мы их используем. Для этого мы можем задействовать метод inputProperties()
.
registerPaint('bubble', class {
static get inputProperties() {
return ['--bubble-size', '--bubble-color'];
}
paint() {
/* ... */
}
});
Переменные могут быть назначены с помощью третьего параметра, переданного в метод paint()
.
paint(context, canvas, properties) {
const circleSize = parseInt(properties.get('--bubble-size').toString());
const circleColor = properties.get('--bubble-color').toString();
const bodyWidth = canvas.width;
const bodyHeight = canvas.height;
const maxX = Math.floor(bodyWidth / circleSize);
const maxY = Math.floor(bodyHeight / circleSize);
for (let y = 0; y < maxY; y++) {
for (let x = 0; x < maxX; x++) {
context.fillStyle = circleColor;
context.beginPath();
context.arc(x * circleSize * 2 + circleSize, y * circleSize * 2 + circleSize, circleSize, 0, 2 * Math.PI, true);
context.closePath();
context.fill();
}
}
}
2. Вы можете генерировать случайные изображения с помощью Math.random()
в методе paint()
.
// CSS
body {
width: 200px;
height: 200px;
background-image: paint(random);
}
// JS
function getRandomHexColor() {
return '#'+ Math.floor(Math.random() * 16777215).toString(16)
}
class Random {
paint(context, canvas) {
const color1 = getRandomHexColor();
const color2 = getRandomHexColor();
const gradient = context.createLinearGradient(0, 0, canvas.width, 0);
gradient.addColorStop(0, color1);
gradient.addColorStop(1, color2);
context.fillStyle = gradient;
context.fillRect(0, 0, canvas.width, canvas.height);
}
}
registerPaint('random', Random);
Если вы хотите узнать больше о том, как это реализовать, дайте мне знать в разделе комментариев ниже.
Это потрясающе, не так ли?
Но каждая хорошая вещь имеет хотя бы одну плохую сторону. Этот API имеет очень ограниченную поддержку в браузерах.
Поддержка браузеров
![Источник: Can I Use Источник: Can I Use](https://habrastorage.org/getpro/habr/upload_files/419/c17/8d6/419c178d602a4381d10a74358ce1c940.png)
Большинство браузеров, включая Firefox, не поддерживают CSS Paint API. Только браузеры на основе Chrome и Chromium пока что имеют полную поддержку. Будем надеяться, что поддержка браузеров улучшится в ближайшем будущем.
Резюме
CSS Paint API чрезвычайно полезен для сокращения времени отклика сетевых запросов. Это достигается путем генерации некоторых изображений программно, а не путем их получения через сетевые запросы.
Кроме того, основные преимущества, на мой взгляд, следующие.
Возможность создавать полностью настраиваемые изображения в отличие от статических.
Создание изображений, не зависящих от разрешения (больше никаких изображений плохого качества на вашем сайте).
Важным моментом является то, что вы можете использовать полифил (polyfill) в качестве обходного пути для поддержки таких браузеров, как Firefox, которые еще не реализовали CSS Painting API.
Сообщите ваши мысли по этому поводу тоже. Спасибо за чтение!
Узнать подробнее о курсе "JavaScript Developer. Professional".
Смотреть открытый вебинар на тему «Vue 3 — возможности новой версии одного из самых популярных фронтенд фреймворков».