Add paint function for fast CSS painting API expriment
This commit is contained in:
parent
5c7b9fd7b7
commit
2dd12aa6f8
|
|
@ -326,6 +326,10 @@ function get_exposed(random) {
|
|||
return value => value;
|
||||
},
|
||||
|
||||
paint() {
|
||||
return value => value;
|
||||
},
|
||||
|
||||
path() {
|
||||
return value => value;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class Rules {
|
|||
this.coords = [];
|
||||
this.doodles = {};
|
||||
this.canvas = {};
|
||||
this.paint = {};
|
||||
this.shaders = {};
|
||||
this.paths = {};
|
||||
this.reset();
|
||||
|
|
@ -58,6 +59,7 @@ class Rules {
|
|||
this.coords = [];
|
||||
this.doodles = {};
|
||||
this.canvas = {};
|
||||
this.paint = {};
|
||||
this.shaders = {};
|
||||
for (let key in this.rules) {
|
||||
if (key.startsWith('#c')) {
|
||||
|
|
@ -112,7 +114,7 @@ class Rules {
|
|||
}
|
||||
|
||||
is_composable(name) {
|
||||
return ['doodle', 'shaders', 'canvas'].includes(name);
|
||||
return ['doodle', 'shaders', 'canvas', 'paint'].includes(name);
|
||||
}
|
||||
|
||||
compose_argument(argument, coords, extra = []) {
|
||||
|
|
@ -138,6 +140,8 @@ class Rules {
|
|||
return this.compose_shaders(value, coords);
|
||||
case 'canvas':
|
||||
return this.compose_canvas(value, coords);
|
||||
case 'paint':
|
||||
return this.compose_paint(value, arg.arguments.slice(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -187,6 +191,17 @@ class Rules {
|
|||
return '${' + id + '}';
|
||||
}
|
||||
|
||||
compose_paint(code, rest = []) {
|
||||
let commands = code;
|
||||
let result = rest.map(group => get_value(group[0])).join(',');
|
||||
if (result.length) {
|
||||
commands = code + ',' + result;
|
||||
}
|
||||
let id = this.unique_id('paint');
|
||||
this.paint[id] = { code: commands };
|
||||
return '${' + id + '}';
|
||||
}
|
||||
|
||||
compose_path(commands) {
|
||||
let id = this.unique_id('path');
|
||||
this.paths[id] = {
|
||||
|
|
@ -223,6 +238,8 @@ class Rules {
|
|||
result += this.compose_shaders(value, coords); break;
|
||||
case 'canvas':
|
||||
result += this.compose_canvas(value, coords); break;
|
||||
case 'paint':
|
||||
result += this.compose_paint(value, val.arguments.slice(1)); break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
@ -316,7 +333,7 @@ class Rules {
|
|||
}
|
||||
}
|
||||
|
||||
if (prop === 'background' && (value.includes('shader') || value.includes('canvas'))) {
|
||||
if (prop === 'background' && (value.includes('shader') || value.includes('canvas') || value.includes('paint'))) {
|
||||
rule += 'background-size: 100% 100%;';
|
||||
}
|
||||
|
||||
|
|
@ -544,6 +561,7 @@ class Rules {
|
|||
shaders: this.shaders,
|
||||
paths: this.paths,
|
||||
canvas: this.canvas,
|
||||
paint: this.paint,
|
||||
definitions: definitions,
|
||||
uniforms: this.uniforms
|
||||
}
|
||||
|
|
|
|||
30
src/index.js
30
src/index.js
|
|
@ -6,6 +6,7 @@ import seedrandom from './lib/seedrandom';
|
|||
import { svg_to_png } from './svg';
|
||||
import { draw_shader } from './shader.js';
|
||||
import { draw_canvas } from './canvas.js';
|
||||
import { make_paint } from './paint.js';
|
||||
import { uniform_time } from './uniform';
|
||||
|
||||
import get_props from './utils/get-props';
|
||||
|
|
@ -239,6 +240,10 @@ class Doodle extends HTMLElement {
|
|||
draw_canvas(code, width, height, this.random).then(fn);
|
||||
}
|
||||
|
||||
paint_to_image({ code, cell }, fn) {
|
||||
make_paint(code, this.random).then(fn);
|
||||
}
|
||||
|
||||
shader_to_image({ shader, cell }, fn) {
|
||||
let parsed = parse_shaders(shader);
|
||||
let element = this.doodle.getElementById(cell);
|
||||
|
|
@ -287,16 +292,16 @@ class Doodle extends HTMLElement {
|
|||
this.build_grid(compiled, this.grid_size);
|
||||
}
|
||||
|
||||
replace({ doodles, shaders, paths, canvas }) {
|
||||
replace({ doodles, shaders, paths, canvas, paint }) {
|
||||
let doodle_ids = Object.keys(doodles);
|
||||
let shader_ids = Object.keys(shaders);
|
||||
let path_ids = Object.keys(paths);
|
||||
let canvas_ids = Object.keys(canvas);
|
||||
let paint_ids = Object.keys(paint);
|
||||
return input => {
|
||||
if (!doodle_ids.length && !shader_ids.length && !path_ids.length && !canvas_ids.length) {
|
||||
if (!doodle_ids.length && !shader_ids.length && !path_ids.length && !canvas_ids.length && !paint_ids.length) {
|
||||
return Promise.resolve(input);
|
||||
}
|
||||
|
||||
let mappings = [].concat(
|
||||
doodle_ids.map(id => {
|
||||
if (input.includes(id)) {
|
||||
|
|
@ -325,6 +330,15 @@ class Doodle extends HTMLElement {
|
|||
return Promise.resolve('');
|
||||
}
|
||||
}),
|
||||
paint_ids.map(id => {
|
||||
if (input.includes(id)) {
|
||||
return new Promise(resolve => {
|
||||
this.paint_to_image(paint[id], value => resolve({ id, value }));
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
}),
|
||||
path_ids.map(id => {
|
||||
if (input.includes(id)) {
|
||||
return Promise.resolve({ id, value: '#' + id });
|
||||
|
|
@ -337,11 +351,17 @@ class Doodle extends HTMLElement {
|
|||
return Promise.all(mappings).then(mapping => {
|
||||
if (input.replaceAll) {
|
||||
mapping.forEach(({ id, value }) => {
|
||||
input = input.replaceAll('${' + id + '}', `url(${value})`);
|
||||
input = input.replaceAll(
|
||||
'${' + id + '}',
|
||||
/^paint/.test(id) ? value : `url(${value})`
|
||||
);
|
||||
});
|
||||
} else {
|
||||
mapping.forEach(({ id, value }) => {
|
||||
input = input.replace('${' + id + '}', `url(${value})`);
|
||||
input = input.replace(
|
||||
'${' + id + '}',
|
||||
/^paint/.test(id) ? value : `url(${value})`
|
||||
)
|
||||
});
|
||||
}
|
||||
return input;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
import { un_entity } from './utils/index';
|
||||
|
||||
let counter = 1;
|
||||
let cache = {};
|
||||
|
||||
function make_paint(code, random) {
|
||||
if (cache[code]) {
|
||||
return Promise.resolve(cache[code]);
|
||||
}
|
||||
|
||||
let name = 'css-doodle-paint-' + counter++;
|
||||
let wrapped = `
|
||||
registerPaint('${name}', class {
|
||||
${ un_entity(code) }
|
||||
})
|
||||
`;
|
||||
let blob = new Blob([wrapped], { type: 'text/javascript' });
|
||||
try {
|
||||
if (CSS.paintWorklet) {
|
||||
CSS.paintWorklet.addModule(URL.createObjectURL(blob));
|
||||
}
|
||||
} catch(e) {}
|
||||
|
||||
return Promise.resolve(cache[code] = `paint(${name})`);
|
||||
}
|
||||
|
||||
export {
|
||||
make_paint
|
||||
}
|
||||
Loading…
Reference in New Issue