Низкоуровневые API, которые подключаются к процессу стилизации и макета движка рендеринга вашего браузера.
Примечание. Исходный код демонстрации, обсуждаемой во второй половине этой статьи, можно найти на GitLab.
вступление
Как я уже упоминал в своей недавней статье об анимации холста внутри компонентов React, я люблю холст HTML. Так что я был очень взволнован, узнав о новых API-интерфейсах CSS Houdini, когда читал короткую статью об этом на css-tricks.com, написанную Стивеном Фулгхамом.
Основная причина моего восхищения заключается в том, что API рисования позволяет создавать пользовательские изображения CSS путем рисования на PaintRenderingContext2D (который в значительной степени является точной копией 2D-контекста, который мы рисуем, когда используем обычный Canvas API - за исключением небольшого набора функций).
Используя API рисования, мы можем программно рисовать изображения и использовать эти изображения в нашем CSS. При рисовании мы можем получать параметры с информацией, поступающей из DOM и применяемых таблиц стилей.
Веб-документы MDN описывают это так:
Houdini - это набор низкоуровневых API-интерфейсов, которые раскрывают части движка CSS, давая разработчикам возможность расширять CSS, подключаясь к процессу стилизации и компоновки движка рендеринга браузера.
Я нахожу это очень захватывающим, особенно с учетом того, что мы видим признаки того, что все основные браузеры это реализуют:
В этой статье мы рассмотрим CSS Painting API (и Worklets).
Важное примечание. В целом CSS Houdini все еще является экспериментальной технологией. Но, как упоминалось ранее, большинство браузеров реализуют это или серьезно рассматривают возможность реализации. Google Chrome - это ранний адаптер, который поддерживает Painting API начиная с версии 65, так что это браузер, который мы будем использовать сегодня.
CSS Painti API-интерфейс
Используя этот API, мы можем программно рисовать изображения и использовать эти изображения в нашем CSS. Вот что мы создадим:
Как ни странно, это три элемента DIV и только три элемента DIV.
Об этом свидетельствует наш файл index.html:
«Стилизация» (рисование…) фона трех панелей выполняется программно с помощью API рисования. Все три панели нарисованы одной и той же функцией.
Давайте посмотрим на CSS-класс pane
в нашей таблице стилей:
Мы рисуем что-то, называемое pane, в строке 2. Это требует объяснения, и мы скоро его рассмотрим.
Важно отметить, что функция рисования не выполняется только один раз. Он выполняется - и перерисовывает изображение - всякий раз, когда движок рендеринга браузера дает ему инструкции сделать это. Примеры этого: когда пользователь изменяет размер окна браузера или когда другие свойства CSS элемента DIV изменяются, и элемент DIV получает другое измерение.
Поскольку наша функция будет «подключена» к механизму рендеринга, это очень эффективная и недорогая операция.
Кроме того, стоит упомянуть, что все наши панели имеют разный размер шрифта (имейте это в виду, мы еще вернемся к нему позже). И мы видим, что используются две пользовательские переменные CSS:
‑‑dot‑spacing
‑‑pane‑color
В переменных CSS нет ничего нового. Они существуют с 2014/2016 (соответственно Firefox / Google Chrome). Но один из новых API-интерфейсов CSS Houdini, называемый API свойств и значений CSS, позволяет нам зарегистрировать эти пользовательские переменные, чтобы браузер узнал о них больше. удобно.
Внутри нашей таблицы стилей мы можем зарегистрировать их следующим образом:
Обратите внимание, что мы также могли сделать это на JavaScript. Результат будет таким же.
Так зачем мы это делаем? Теперь наш браузер и его движок визуализации знают подробности об этих свойствах. Он знает, что ‑‑pane‑color
содержит значение цвета и что значение по умолчанию - «# 646464». И ‑‑dot‑spacing
содержит значение длины, значение по умолчанию - «5 пикселей».
Две наши новые переменные теперь называются зарегистрированными пользовательскими переменными.
Вернемся к этой строке:
background-image: paint(pane);
API рисования позволяет нам рисовать изображение. Функция paint
получает один параметр. Этот параметр представляет собой класс JavaScript, зарегистрированный как Paint в файле с именем worklet.js
:
Но! Этот код не может быть выполнен в нашей обычной среде выполнения JavaScript. Он должен выполняться внутри так называемого - отсюда и название файла - Worklet:
«Интерфейс Worklet - это облегченная версия Web Workers, которая дает разработчикам доступ к низкоуровневым частям конвейера рендеринга. С помощью Worklets вы можете запускать код JavaScript и WebAssembly для рендеринга графики или обработки звука там, где требуется высокая производительность ».
Мы можем убедиться, что Worklet будет выполнен, добавив следующую строку в наш обычный файл JavaScript (main.js
), который загружается внутри index.html, например:
// main.js CSS.paintWorklet.addModule("worklet.js");
Если этот вызов возвращает ошибку, ваш браузер не поддерживает Painting API.
Теперь наш класс Paint «Pane» зарегистрирован под именем «pane», и мы можем использовать его в нашем CSS, как мы видели ранее:
background-image: paint(pane);
Подробная информация о панели класса Paint
Давайте подробно рассмотрим класс Paint внутри worklet.js:
Статическая функция inputProperties
должна возвращать список свойств CSS, которые нас интересуют, когда мы будем рисовать изображение. Это произвольно, и вы можете добавить любое свойство CSS, какое захотите.
Значение, возвращаемое contextOptions
, указывает, что мы хотим использовать прозрачность в нашем холсте.
И, наконец, в строке 10 - функция paint
. В этой функции мы сделаем фактический рисунок. В нашем случае он получает три параметра:
ctx
: 2D-контекст нашего холста. Это должно стать сигналом, если вы знакомы с обычным элементом HTML Canvas.size
: экземпляр PaintSize с двумя свойствами:.width
и.height
. Это вычисленные размеры элемента HTML, для которого мы рисуем изображение. Включая отступы, если они установлены.styleMap
: доступное только для чтения представление блока CSS-декларации (источник). Это экземплярStylePropertyMapReadOnly
и содержит значения только тех свойств, которые мы определили внутри статической функцииinputProperties
.
Подробнее о последнем параметре вы можете прочитать об API типизированной объектной модели CSS и / или прочитать об интерфейсе StylePropertyMapReadOnly.
Совет. Вы можете получить полный StylePropertyMapReadOnly (содержащий все вычисленные стили CSS) для любого элемента HTML в DOM, вызвав computedStyleMap в браузерах, которые его поддерживают:
const styleMap = document.getElementById('myElement').computedStyleMap();
Чтобы прояснить, как мы можем получить значения из такого экземпляра, я создал фрагмент с некоторыми встроенными комментариями:
Рисование актуального образа
Вернемся к логике нашей маленькой демонстрации. Осталось только содержимое тела нашей функции рисования.
Мы могли бы начать с простого рисования заполненного прямоугольника в качестве фонового изображения (вы должны распознать команды рисования на обычном холсте HTML):
… Который будет выглядеть так:
Обратите внимание, как мы использовали наше настраиваемое свойство CSS ‑‑pane‑color
для динамической установки стиля заливки.
Используя инструменты разработчика нашего браузера, мы можем даже обновить значение цвета, и фоновое изображение будет мгновенно перекрашено!
Если мы обновим нашу функцию рисования с помощью более причудливой логики (вы можете посмотреть подробности в файле worklet.js в репозитории), наше фоновое изображение будет выглядеть так:
CSS переходы
Обратите внимание на последовательность точек в правом нижнем углу. Расстояние между этими точками определяется значением настраиваемого свойства CSS ‑‑dot‑spacing
, которое имеет значение по умолчанию «5 пикселей».
Давайте немного повеселимся, добавив к этому свойству переход. Мы также увеличиваем значение расстояния между точками, когда наводим курсор на наш элемент .pane
:
… Что приводит к плавной анимации при наведении курсора на наши элементы:
Он показывает, насколько производительна наша настраиваемая функция рисования и что она может выполняться более 60 раз в секунду.
Причина, по которой мы можем добавить переход к пользовательской переменной CSS, заключается в том, что мы зарегистрировали свойство ранее (см. Строки 1–5 в сути).
Совет. Мы также могли бы добавить бесконечную анимацию CSS для одного из наших настраиваемых свойств CSS, что привело бы к созданию настраиваемого анимированного фона!
Заключение
Я нахожу Houdini Painting API не только интересным, но и простым для понимания и мощным (производительным). Я полон идей по использованию этой новой функции, но мне нужно набраться терпения и подождать, пока все основные браузеры не поддержат ее, прежде чем мы сможем рассмотреть возможность ее использования в производственной среде.
Спасибо за ваше время!