Эта статья основана на моем сообщении в польском блоге на ту же тему.

Если вы следите за сообществом JavaScript, вы, вероятно, знаете о CSS в JS. Это способ поместить ваш CSS в файл JavaScript вместо отдельного файла CSS. В этой статье я показываю противоположное решение: это объект JSON, помещенный в ваш файл CSS, который анализируется с помощью JavaScript (вы, вероятно, можете поместить JS в CSS, но я его не тестировал). Причина, по которой мы делаем это, заключается в том, чтобы управлять CSS на основе JavaScript, API, который является частью Houdini.

Гудини

Houdini - это набор новых API, созданных для одной цели. Таким образом, разработчики могут контролировать поведение движка CSS. Чтобы иметь возможность подключиться к его внутренностям и заставить его работать так, как они хотят. Некоторые из API уже реализованы, некоторые планируется реализовать, а некоторые все еще находятся в процессе разработки, поэтому они могут измениться. Вы можете увидеть статус Houdini на сайте ishoudinireadyyet.com.

Paint Worklet

Этот рабочийлет похож на обычного рабочего (отдельный поток выполняется в браузере), но он позволяет зарегистрировать класс «рисования», который имеет доступ к холсту, например API, который можно использовать внутри CSS для рендеринга вещей (например, с использованием фонового изображения).

Чтобы зарегистрировать рабочий лист рисования, вы выполняете этот код:

CSS.paintWorklet.addModule('plik.js');

Внутри этого файла вы можете создать специальный класс, подобный приведенному ниже:

class Circle {
static get inputProperties() {
        return ['--pointer-x', '--pointer-y', '--pointer-options'];
    }
paint(context, geom, properties) {
        var x = properties.get('--pointer-x').value || 0;
        var y = properties.get('--pointer-y').value || 0;
        const prop = properties.get('--pointer-options');
        // destructure object props with defaults
        const {
            background,
            color,
            width
        } = Object.assign({
            color: 'white',
            background: 'black',
            width: 10
        }, JSON.parse(prop.toString()));
        // draw circle at point
        context.fillStyle = color;
        console.log({x,y, color, background, width})
        context.beginPath();
        const r = Math.floor(width / 2);
        context.arc(x, y, r, 0, 2 * Math.PI, false);
        context.closePath();
        context.fill();
    }
}

тогда вы можете зарегистрировать этот класс как paint:

registerPaint('circle', Circle);

JSON в CSS

Если вы посмотрите на предыдущий код класса, вы увидите следующее:

const prop = properties.get('--pointer-options');
JSON.parse(prop.toString());

Итак, мы получаем необработанные данные из CSS и анализируем их как JSON. В CSS это выглядит так:

div {
    height: 100vh;
    background-image: paint(circle);
    --pointer-x: 20px;
    --pointer-y: 10px;
    --pointer-options: {
        "color": "rebeccapurple",
        "width": 20
    };
}

Каждый раз, когда вы меняете настраиваемое свойство (одно с двумя дефисами впереди, также называемое переменной css), оно будет повторно отображать фон.

ПРИМЕЧАНИЕ. В прошлый раз, когда я тестировал этот код, переменные CSS должны были содержать тире в середине, иначе они не работали бы с рисованием.

Когда вы добавляете настраиваемые свойства в свой CSS, вам также необходимо их зарегистрировать, чтобы они имели тип:

CSS.registerProperty({
    name: '--pointer-x',
    syntax: '<length>',
    inherits: false,
    initialValue: '10px'
});
CSS.registerProperty({
    name: '--pointer-y',
    syntax: '<length>',
    inherits: false,
    initialValue: '10px'
});
CSS.registerProperty({
    name: '--pointer-options',
    inherits: false,
    initialValue: '{}'
});

И последнее, что вы можете сделать, это изменить свойства CSS при перемещении мыши:

document.querySelector('div').addEventListener('mousemove', (e) => {
    const style = e.target.style;
    style.setProperty('--pointer-x', event.clientX + 'px');
    style.setProperty('--pointer-y', event.clientY + 'px');
});

Вы можете проверить весь код в этой демонстрации CodePen.

Если вам понравилась эта статья, вы можете подписаться на меня в твиттере @jcubic.