API CSS Paint

Nouvelles possibilités dans Chrome 65

L'API CSS Paint (également appelée "CSS Custom Paint" ou "Worklet de peinture de Houdini") est activée par défaut à partir de Chrome 65. De quoi s'agit-il ? Que pouvez-vous faire ? avec lui ? Comment cela fonctionne-t-il ? Poursuivez la lecture...

L'API CSS Paint vous permet de générer une image par programmation chaque fois qu'un code CSS attend une image. Établissements tels que background-image ou border-image sont généralement utilisés avec url() pour charger un fichier image ou avec CSS intégré. des fonctions telles que linear-gradient(). Au lieu de les utiliser, vous pouvez désormais utiliser paint(myPainter) pour référencer un worklet de peinture.

Écrire un Worklet de peinture

Pour définir un Worklet Paint appelé myPainter, nous devons charger un objet "Paint CSS" le fichier Worklet à l'aide de CSS.paintWorklet.addModule('my-paint-worklet.js'). Dans ce nous pouvons utiliser la fonction registerPaint pour enregistrer une classe de Worklet Paint:

class MyPainter {
  paint(ctx, geometry, properties) {
    // ...
  }
}

registerPaint('myPainter', MyPainter);

Dans le rappel paint(), nous pouvons utiliser ctx de la même manière que CanvasRenderingContext2D tel que nous le connaissons depuis <canvas>. Si vous savez comment lorsque vous dessinez dans un <canvas>, vous pouvez dessiner avec un peinture. geometry nous indique la largeur et la hauteur de la toile dont nous disposons. properties Je le compte plus loin dans cet article.

À titre d'exemple d'introduction, écrivons un travaillet de peinture damier et utilisons-le en tant qu'image de fond d'un <textarea>. (J'utilise une zone de texte, car elle redimensionnable par défaut):

<!-- 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 vous avez déjà utilisé <canvas>, ce code devrait vous être familier. Voir le direct démonstration ici.

Zone de texte avec un motif de damier comme image de fond
. Zone de texte avec un motif de damier comme image de fond.

La différence par rapport à l'utilisation d'une image de fond courante ici est que le modèle seront redessinés à la demande, chaque fois que l'utilisateur redimensionne la zone de texte. Cela signifie l'image de fond est toujours aussi grande qu'elle doit l'être, y compris pour les écrans haute densité.

C'est plutôt cool, mais c'est aussi assez statique. Voudrions-nous écrire une nouvelle "Worklet" à chaque fois que nous voulions le même schéma, mais avec des tailles différentes carrés ? La réponse est non !

Paramétrer votre Worklet

Heureusement, le Worklet de peinture peut accéder à d'autres propriétés CSS, où le paramètre supplémentaire properties entre en jeu. En attribuant à la classe inputProperties, vous pouvez vous abonner aux modifications apportées à n'importe quelle propriété CSS, y compris les propriétés personnalisées. Les valeurs vous seront fournies via le Paramètre 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);

Nous pouvons maintenant utiliser le même code pour tous les différents types de damier. Mais même Nous pouvons désormais accéder aux outils de développement et manipuler les valeurs jusqu'à ce que nous trouvions le bon look.

Navigateurs non compatibles avec la fonctionnalité Paint

Au moment de la rédaction de ce document, seul Chrome dispose d'un Worklet de peinture. Pendant l'activité sont des signaux positifs de tous les autres fournisseurs de navigateurs, les progrès sont limités. Pour vous tenir informé, consultez la section Is Houdini Ready Yet? (Est-ce que Houdini est prêt pour l'instant ?) régulièrement. En attendant, assurez-vous d'utiliser les pour continuer à exécuter votre code même en l'absence de prise en charge de Paint Worklet de VM. Pour vous assurer que tout fonctionne comme prévu, vous devez ajuster votre code dans deux emplacements: le CSS et le JS.

Vous pouvez détecter la prise en charge du Worklet de peinture en JavaScript en vérifiant l'objet CSS: js if ('paintWorklet' in CSS) { CSS.paintWorklet.addModule('mystuff.js'); } Côté CSS, deux options s'offrent à vous. Vous pouvez utiliser @supports:

@supports (background: paint(id)) {
  /* ... */
}

Une astuce plus compacte consiste à utiliser le fait que le CSS invalide et, par conséquent, ignore une déclaration de propriété entière si celle-ci contient une fonction inconnue. Si vous spécifiez une propriété deux fois : d'abord sans le Worklet de peinture, puis avec le travaillet de peinture — vous obtenez une amélioration progressive:

textarea {
  background-image: linear-gradient(0, red, blue);
  background-image: paint(myGradient, red, blue);
}

Dans les navigateurs compatibles avec le Worklet Paint, la deuxième déclaration de background-image écrasera la première. Dans les navigateurs non compatibles pour le Worklet Paint, la deuxième déclaration n'est pas valide et sera supprimée, la première déclaration en vigueur.

Polyremplissage de peinture CSS

Pour de nombreuses utilisations, il est également possible d'utiliser le Polyremplissage de peinture CSS qui permet la prise en charge des CSS Custom Paint and Paint dans les navigateurs récents.

Cas d'utilisation

Il existe de nombreux cas d'utilisation des worklets de peinture, certains d'entre eux plus évidents que autres. L’une des plus évidentes est l’utilisation d’un Worklet de peinture pour réduire la taille de votre DOM. Souvent, les éléments sont ajoutés uniquement pour créer des embellissements à l'aide de CSS. Par exemple, dans Material Design Lite, le bouton avec l'effet d'ondulation, qui contient deux éléments <span> supplémentaires pour implémenter la de l'ondulation. Si vous avez beaucoup de boutons, le nombre total de boutons des éléments DOM, ce qui peut entraîner une dégradation des performances sur mobile. Si vous Implémenter l'effet d'ondulation à l'aide d'un Worklet de peinture au lieu de cela, vous vous retrouvez avec 0 élément supplémentaire et un seul travaillet de peinture. De plus, vous disposez de quelque chose beaucoup plus facile à personnaliser et paramétrer.

Un autre avantage de l'utilisation du Worklet de peinture est que, dans la plupart des cas, le travaillet de peinture est peu en termes d’octets. Évidemment, Compromis: votre code s'exécute chaque fois que la taille du canevas ou les paramètres changent. Si votre code est complexe et prend du temps, il peut introduire les à-coups. Chrome travaille sur le déplacement des applets de peinture hors du thread principal pour que même les jobs de peinture de longue durée n'affectent pas la réactivité thread.

Pour moi, la perspective la plus passionnante est que le Worklet de peinture permet une polyfilling de fonctionnalités CSS qu'un navigateur ne possède pas encore Par exemple, pour émuler des dégradés coniques jusqu'à ils sont intégrés à Chrome. Autre exemple: lors d'une réunion CSS, vous pouvez désormais avoir plusieurs couleurs de bordure. Pendant cette réunion, mon collègue Ian Kilpatrick a créé un polyfill pour ce nouveau CSS. le comportement à l'aide d'un Worklet de peinture.

Sortir des sentiers battus

La plupart des gens commencent à penser aux images de fond et aux images de bordure lorsqu’ils en savoir plus sur le worklet de peinture. Un cas d'utilisation moins intuitif du Worklet de peinture est mask-image pour que les éléments DOM aient des formes arbitraires. Par exemple, diamond:

<ph type="x-smartling-placeholder">
</ph> Élément DOM en forme de losange. <ph type="x-smartling-placeholder">
</ph> Élément DOM en forme de losange.

mask-image prend une image dont la taille correspond à celle de l'élément. Zones géographiques l'image de masque est transparente, l'élément est transparent. Zones où le masque l'image est opaque, l'élément opaque.

Désormais disponible dans Chrome

Le Worklet de peinture est présent dans Chrome Canary depuis un certain temps. Avec Chrome 65, est activée par défaut. Lancez-vous et essayez les nouvelles possibilités ce travaillet de peinture s'ouvre et montre-nous ce que vous avez créé ! Besoin d'inspiration ? découvrez la collection de Vincent De Oliveira.