Nuevas posibilidades en Chrome 65
La API de CSS Paint (también conocida como "CSS Custom Paint" o "Houdini's Paint worklet") es habilitado de forma predeterminada a partir de Chrome 65. ¿Qué es? ¿Qué puedes hacer? con él? ¿Cómo funciona? Bueno, sigue leyendo, ¿sí?
La API de pintura de CSS te permite generar una imagen de manera programática cada vez que se crea un CSS
espera una imagen. Propiedades como background-image
o border-image
Por lo general, se usan con url()
para cargar un archivo de imagen o con CSS integrado.
funciones como linear-gradient()
. En lugar de usarlos, ahora puedes usar
paint(myPainter)
para hacer referencia a un worklet de pintura.
Cómo escribir un worklet de pintura
Para definir un worklet de pintura llamado myPainter
, debemos cargar un elemento de pintura de CSS.
un archivo worklet con CSS.paintWorklet.addModule('my-paint-worklet.js')
. En ese
podemos usar la función registerPaint
para registrar una clase de worklet de pintura:
class MyPainter {
paint(ctx, geometry, properties) {
// ...
}
}
registerPaint('myPainter', MyPainter);
Dentro de la devolución de llamada paint()
, podemos usar ctx
de la misma manera que lo haríamos con un
CanvasRenderingContext2D
, tal como la conocemos por <canvas>
. Si sabes cómo
dibuja en un <canvas>
, puedes dibujar en un worklet de pintura. geometry
nos indica la
ancho y alto del lienzo que tenemos a nuestra disposición. properties
Voy a
más adelante en este artículo.
Como ejemplo introductorio, escribamos un worklet de pintura de tablero de ajedrez y lo usemos
como imagen de fondo de un <textarea>
. (Estoy usando un área de texto porque es
puede cambiar de tamaño de forma predeterminada):
<!-- index.html -->
<!doctype html>
<style>
textarea {
background-image: paint(checkerboard);
}
</style>
<textarea></textarea>
<script>
CSS.paintWorklet.addModule('checkerboard.js');
</script>
// checkerboard.js
class CheckerboardPainter {
paint(ctx, geom, properties) {
// Use `ctx` as if it was a normal canvas
const colors = ['red', 'green', 'blue'];
const size = 32;
for(let y = 0; y < geom.height/size; y++) {
for(let x = 0; x < geom.width/size; x++) {
const color = colors[(x + y) % colors.length];
ctx.beginPath();
ctx.fillStyle = color;
ctx.rect(x * size, y * size, size, size);
ctx.fill();
}
}
}
}
// Register our class under a specific name
registerPaint('checkerboard', CheckerboardPainter);
Si ya usaste <canvas>
, este código debería resultarte familiar. Consulta
en vivo
demostración
aquí.
![Área de texto con un patrón de damas como imagen de fondo](https://developer.chrome.google.cn/static/blog/paintapi/image/textarea-a-checkerboard-bd94c5b6c6b65.png?authuser=7&hl=es-419)
La diferencia de usar una imagen de fondo común aquí es que el patrón se volverá a dibujar a pedido cada vez que el usuario cambie el tamaño del área de texto. Esto significa la imagen de fondo siempre sea exactamente tan grande como debe ser, con las adicional para pantallas de alta densidad.
Eso es genial, pero también es bastante estático. ¿Quisiéramos escribir un nuevo cada vez que queríamos el mismo patrón, pero con tamaños diferentes cuadrados? La respuesta es no.
Parametrización de tu worklet
Por suerte, el worklet de pintura puede acceder a otras propiedades de CSS, que es donde la
entra en juego el parámetro adicional properties
. Si le das a la clase un valor
inputProperties
, puedes suscribirte a los cambios realizados en cualquier propiedad de CSS
incluidas las propiedades personalizadas. Los valores se te proporcionarán a través del
Parámetro properties
.
<!-- index.html -->
<!doctype html>
<style>
textarea {
/* The paint worklet subscribes to changes of these custom properties. */
--checkerboard-spacing: 10;
--checkerboard-size: 32;
background-image: paint(checkerboard);
}
</style>
<textarea></textarea>
<script>
CSS.paintWorklet.addModule('checkerboard.js');
</script>
// checkerboard.js
class CheckerboardPainter {
// inputProperties returns a list of CSS properties that this paint function gets access to
static get inputProperties() { return ['--checkerboard-spacing', '--checkerboard-size']; }
paint(ctx, geom, properties) {
// Paint worklet uses CSS Typed OM to model the input values.
// As of now, they are mostly wrappers around strings,
// but will be augmented to hold more accessible data over time.
const size = parseInt(properties.get('--checkerboard-size').toString());
const spacing = parseInt(properties.get('--checkerboard-spacing').toString());
const colors = ['red', 'green', 'blue'];
for(let y = 0; y < geom.height/size; y++) {
for(let x = 0; x < geom.width/size; x++) {
ctx.fillStyle = colors[(x + y) % colors.length];
ctx.beginPath();
ctx.rect(x*(size + spacing), y*(size + spacing), size, size);
ctx.fill();
}
}
}
}
registerPaint('checkerboard', CheckerboardPainter);
Ahora podemos usar el mismo código para todos los tipos diferentes de tableros de ajedrez. Pero incluso mejor, ahora podemos ir a Herramientas para desarrolladores y controlar los valores. hasta encontrar el estilo adecuado.
Navegadores que no admiten el worklet de pintura
Al momento de la redacción, solo Chrome tiene implementado el worklet de pintura. Mientras estás allí son señales positivas de todos los demás proveedores de navegadores, no hay mucho progreso. Para mantenerte al tanto, consulta el artículo Is Houdini Ready Yet? con regularidad. Mientras tanto, asegúrate de usar la para mantener tu código en ejecución incluso si no hay compatibilidad con pintura. worklet. Para asegurarte de que todo funcione como se espera, debes ajustar el código de dos lugares: el CSS y el JS.
Para detectar la compatibilidad con el worklet de pintura en JS, se puede verificar el objeto CSS
:
js
if ('paintWorklet' in CSS) {
CSS.paintWorklet.addModule('mystuff.js');
}
En cuanto al CSS, tiene dos opciones. Puedes usar @supports
:
@supports (background: paint(id)) {
/* ... */
}
Un truco más compacto es usar el hecho de que CSS invalida y, luego, ignora una declaración de propiedad completa si contiene una función desconocida. Si especificas una propiedad dos veces: primero sin worklet de pintura y, luego, con el Paint worklet, obtienes mejora progresiva:
textarea {
background-image: linear-gradient(0, red, blue);
background-image: paint(myGradient, red, blue);
}
En navegadores compatibles con el worklet de pintura, la segunda declaración del
background-image
reemplazará al primero. En navegadores sin compatibilidad
para el worklet de pintura, la segunda declaración no es válida y se descartará,
y deja la primera declaración vigente.
Polyfill de pintura de CSS
Para muchos usos, también es posible utilizar Polifill de pintura de CSS que agrega compatibilidad con los Worklets personalizados de pintura y pintura de CSS a los navegadores modernos.
Casos de uso
Hay muchos casos de uso para los worklets de pintura, algunos de ellos más obvios que
otras personas. Uno de los más obvios es usar el worklet de pintura para reducir el tamaño
de tu DOM. A menudo, los elementos se agregan exclusivamente para crear adornos.
con CSS. Por ejemplo, en Material Design Lite, el botón
con el efecto dominó contiene 2 elementos <span>
adicionales para implementar la
Ondas a sí misma. Si tienes muchos botones, esto puede aumentar
de elementos del DOM y puede llevar a un rendimiento degradado en los dispositivos móviles. Si
implementar el efecto de ondas con el worklet de pintura
en cambio, terminas con 0 elementos adicionales y solo un worklet de pintura.
Además, hay algo mucho más fácil de personalizar
parametrizar.
Otra ventaja de usar el worklet de pintura es que, en la mayoría de los escenarios, es una solución con el worklet de pintura es pequeño en términos de bytes. Por supuesto, el código de pintura se ejecutará cada vez que el tamaño del lienzo o cualquiera de cambian los parámetros. Por lo tanto, si tu código es complejo y tarda mucho, podría introducir bloqueos. Chrome está trabajando para quitar los conjuntos de pintura del subproceso principal para que incluso los trabajos de pintura de larga duración no afectan la capacidad de respuesta de la conversación.
Para mí, el cliente potencial más interesante es que el worklet de pintura polyfill de funciones de CSS que el navegador aún no posee. Un ejemplo sería a polyfills gradientes cónicos hasta que llegan a Chrome de forma nativa. Otro ejemplo: en una reunión de CSS, decidió que ahora puedes tener varios colores de borde. Durante esta reunión sigue en curso, mi colega Ian Kilpatrick escribió un polyfill para este nuevo CSS con el worklet de pintura.
Pensar de manera innovadora.
La mayoría de las personas empieza a pensar en las imágenes de fondo y de borde cuando
aprender sobre el worklet de pintura. Un caso de uso menos intuitivo para el worklet de pintura es
mask-image
para hacer que los elementos del DOM tengan formas arbitrarias. Por ejemplo, un
diamante:
![Elemento del DOM en forma de diamante.](https://developer.chrome.google.cn/static/blog/paintapi/image/a-dom-element-the-shape-5de28c7a5eff9.png?authuser=7&hl=es-419)
mask-image
toma una imagen del tamaño del elemento. Áreas en las que
de enmascaramiento es transparente, el elemento es transparente. Áreas en las que se coloca la mascarilla
es opaca, el elemento opaco.
Ahora en Chrome
El worklet de pintura está en Chrome Canary desde hace un tiempo. Con Chrome 65, es habilitado de forma predeterminada. Prueba las nuevas posibilidades se abrirá ese worklet de pintura y nos mostrará lo que construiste. Para obtener más inspiración, echa un vistazo a la colección de Vincent De Oliveira.