Β Β Β Β @bobrov1989
https://vitaliy-bobrov.github.io/
CSS Paint API
π² π§
π€ π½
We want to use the feature after browser implementation....
We will implement the feature when more developers will use it...
π² π§
π€ π½
Parser
CCSOM
Cascade
Layout
Paint
Composite
some-element {
background-image: paint(my-custom-paint);
}
some-element {
background-image: url('./assets/fallback.jpg');
background-image: paint(my-custom-paint);
}
some-element {
background-image: paint(my-custom-paint);
}
some-element {
background-image: url('./assets/fallback.jpg');
background-image: paint(my-custom-paint);
}
Processed on build
const postcss = require('postcss');
module.exports = postcss.plugin('postcss-fallback-my-paint', (options) => {
return css => {
css.walkRules(rule => {
rule.walkDecls(decl => {
const value = decl.value;
if (value.includes('my-custom-paint')) {
decl.cloneBefore({value: options.fallbackValue});
}
});
});
};
});
class MyCustomPainter {
paint(ctx, geom, props, args) {
/// paint implementation.
}
}
registerPaint('my-custom-paint', MyCustomPainter);
if ('paintWorklet' in CSS) {
CSS.paintWorklet.addModule('custom-paint.js');
}
class CirclesPainter {
paint(ctx, geom) {
const offset = 10;
const size = Math.min(geom.width, geom.height);
const radius = (size / 4) - offset;
const point = radius + offset;
...
}
}
registerPaint('circles', CirclesPainter);
https://vitaliy-bobrov.github.io/css-paint-demos/hello-world/
paint(ctx, geom) {
...
for (let i = 0; i < 2; i++) {
for (let j = 0; j < 2; j++) {
ctx.fillStyle = `rgb(0,
${Math.floor(255 - 42.5 * i)},
${Math.floor(255 - 42.5 * j)})`;
ctx.beginPath();
ctx.arc(
point + (i * (point * 2)),
point + (j * (point * 2)), radius, 0, 2 * Math.PI);
ctx.fill();
}
}
}
https://vitaliy-bobrov.github.io/css-paint-demos/hello-world/
.circles {
background: #000;
background: paint(circles);
}
https://vitaliy-bobrov.github.io/css-paint-demos/hello-world/
static get inputProperties() {
return [
'--circles-offset',
'--circles-count',
'--circles-opacity'
];
}
paint(ctx, geom, props) {
const offset = parseInt(props.get('--circles-offset'), 10) || 0;
const count = parseInt(props.get('--circles-count'), 10) || 2;
const opacity = parseFloat(props.get('--circles-opacity')) || 1;
...
}
https://vitaliy-bobrov.github.io/css-paint-demos/circles-with-params/
.circles {
--circles-count: 2;
--circles-offset: 10;
--circles-opacity: 1;
background: #000;
background: paint(circles);
}
https://vitaliy-bobrov.github.io/css-paint-demos/circles-with-params/
paint(ctx, geom, props) {
const outerR = parseInt(props.get('--chart-outer-radius'), 10) || 100;
const innerR = parseInt(props.get('--chart-inner-radius'), 10) || 0;
const value = parseFloat(props.get('--chart-value')) || 0;
const background = props.get('--chart-background') || 'red';
const foreground = props.get('--chart-foreground') || 'blue';
...
}
https://vitaliy-bobrov.github.io/css-paint-demos/circle-chart/
paint(ctx, geom, props) {
...
ctx.fillStyle = background;
ctx.beginPath();
ctx.arc(x, y, outerRadius, 0, Math.PI * 2, false);
ctx.arc(x, y, innerRadius, 0, Math.PI * 2, true);
ctx.fill();
ctx.fillStyle = foreground;
const sRadian = Math.PI * 1.5;
const eRadian = Math.PI * 2 * (0.75 + value / 100);
ctx.beginPath();
ctx.arc(x, y, outerRadius, sRadian, eRadian, false);
ctx.arc(x, y, innerRadius, eRadian, sRadian, true);
ctx.fill();
}
https://vitaliy-bobrov.github.io/css-paint-demos/circle-chart/
.chart {
--chart-inner-radius: 0;
--chart-outer-radius: 100;
--chart-value: 10;
--chart-background: #795548;
--chart-foreground: #FF5722;
background: #999 paint(circle-chart);
}
https://vitaliy-bobrov.github.io/css-paint-demos/circle-chart/
https://vitaliy-bobrov.github.io/css-paint-demos/qr-code/
.gradient {
background: linear-gradient(to top, white, red);
}
chrome://flags/
static get inputArguments() {
return ['<color>', '<color>'];
}
paint(ctx, geom, props, args) {
...
const [background, foreground] = args;
ctx.fillStyle = background.toString();
...
ctx.fillStyle = foreground.toString();
...
}
https://vitaliy-bobrov.github.io/css-paint-demos/circle-chart-args/
.chart {
--chart-inner-radius: 0;
--chart-outer-radius: 100;
--chart-value: 10;
background: paint(circle-chart, #795548, #FF5722);
}
https://vitaliy-bobrov.github.io/css-paint-demos/circle-chart-args/
https://lab.iamvdo.me/houdini/ripple
requestAnimationFrame(function raf(now) {
const count = Math.floor(now - start);
button.style.cssText = `
--ripple-x: ${x};
--ripple-y: ${y};
--animation-tick: ${count};
`;
if (count > 1000) {
button.classList.remove('animating');
button.style.cssText = `--animation-tick: 0`;
return;
}
requestAnimationFrame(raf);
});
.my-elem {
--my-color: #fff;
background: var(--my-color);
}
.my-elem {
--my-color: #fff;
background: --my-color;
transition: --my-color .3s;
}
.my-elem:hover {
--my-color: red;
}
CSS.registerProperty({
name: '--my-color',
syntax: '<color>',
inherits: false,
initialValue: 'white'
});
https://lab.iamvdo.me/houdini/animating-gradient
Β Β Β Β @bobrov1989
https://vitaliy-bobrov.github.io/