with-canvas
Le travail sur canvas échoue de deux manières différentes : du code visuel joli mais saccadé, ou du code optimisé mais inmaintenable ou inaccessible. Traitez chaque tâche comme une décision d'architecture de rendu avant d'écrire des appels de dessin. Chargez uniquement la référence nommée par la phase actuelle ; ne préchargez pas toutes les références.
Phase 1 - Classifier le travail canvas
Identifiez la charge de travail dominante avant de choisir les API :
- Rejeter canvas : préférez DOM/CSS/SVG/vidéo lorsque la scène est principalement du texte, des contrôles accessibles, une mise en page documentaire, une iconographie simple, une animation CSS, une lecture multimédia ou un petit nombre de formes vectorielles redimensionnables.
- Animation décorative : ambiance non interactive, particules d'arrière-plan, étoiles, oiseaux, boucles procédurales.
- Rendu de données : graphiques, cartes, heatmaps, grands nuages de points, mesures fréquemment mises à jour.
- Art génératif : dessin aléatoire/semé, croquis créatifs, systèmes procéduraux, images exportables.
- Outil interactif : entrée pointeur/clavier, sélection, glisser, objets éditables, test de hit.
- Jeu/simulation : boucle de mise à jour fixe, entités dynamiques, collision/physique, scène en couches.
- Canvas WebGL/moteur : Three.js/Babylon.js/autre moteur possédant des ressources GPU.
LECTURE OBLIGATOIRE : si la charge de travail est une animation décorative ou de l'art génératif, lisez references/visual-quality.md — pour ces deux tâches, le rendu est l'objectif, et les bonnes pratiques de perf/a11y seules produisent une sortie générique. Ne le chargez PAS pour le rendu de données, les outils, les jeux ou les canvas de moteur.
Condition de sortie : énoncez la charge de travail, pourquoi canvas est la primitive appropriée, le taux de rafraîchissement cible, le nombre d'objets attendu, le modèle d'interaction, et si le canvas est décoratif ou sémantiquement significatif.
Phase 2 - Choisir le modèle de rendu
Utilisez Canvas 2D brut lorsque la scène est principalement du dessin en mode immédiat, du travail pixel, des sprites, une animation simple, ou que la taille du bundle est importante.
Utilisez une bibliothèque à mode retenu lorsque l'application a besoin d'objets éditables, de sélection, de glisser-déposer, d'un graphe de scène en couches, de délégation d'événements ou de sérialisation.
Utilisez p5.js pour les croquis, l'art génératif, l'enseignement/le prototypage, ou le codage créatif où l'ergonomie setup/draw est plus importante que l'intégration avec un framework.
Utilisez Paper.js pour les workflows d'édition vectorielle : chemins, segments, géométrie de Bézier, test de hit, import/export SVG, documents vectoriels en couches.
Utilisez Konva pour l'UI d'application sur canvas : intégrations React/Vue/Svelte, formes déplaçables, couches, formes mises en cache, contrôles d'écoute d'événements.
Utilisez Pencil.js pour des abstractions légères de scène/composant lorsque son modèle de composant convient et que la fraîcheur des dépendances est acceptable pour le projet.
Utilisez Three.js/Babylon.js ou WebGL directement lorsque le coût dominant est le rendu 3D/GPU, les shaders, les caméras, les matériaux, ou les charges de travail importantes de maillage/sprite.
LECTURE OBLIGATOIRE : si vous choisissez une bibliothèque ou révisez un choix de bibliothèque, lisez references/library-selection.md. Ne chargez PAS les références de performance ou de revue à moins que la tâche n'atteigne ces phases.
Avant d'installer une bibliothèque canvas ou d'écrire du code d'API de bibliothèque non trivial, vérifiez la documentation actuelle avec Context7 si disponible ; sinon, utilisez la documentation officielle. Ne vous fiez pas aux API mémorisées pour p5.js, Paper.js, Pencil.js, Konva, ZIM, Three.js ou Babylon.js.
Condition de sortie : nommez le modèle et les alternatives rejetées avec des raisons d'une ligne.
Phase 3 - Concevoir la boucle et l'état
Séparez le code canvas en cycle de vie, mise à jour d'état, rendu, entrée, redimensionnement et démontage. Pour les composants de framework, gardez le moteur canvas impératif derrière une seule frontière montage/init.
Utilisez requestAnimationFrame pour l'animation visible. Suivez delta à partir du timestamp RAF lorsque la vitesse de simulation doit être stable entre les taux de rafraîchissement. Annulez RAF lors du démontage, mettez en pause ou réduisez le travail lorsqu'il est caché, et respectez prefers-reduced-motion.
Choisissez l'une de ces stratégies de redessin :
- Redessin complet : acceptable pour les petites scènes décoratives où la simplicité l'emporte.
- Rectangles sales : objets en mouvement avec de petits changements délimités et un arrière-plan stable.
- Canvas en couches : arrière-plan statique/lent, entités dynamiques, superposition UI/interaction.
- Sprite/cache blits : formes coûteuses répétées, texte, marqueurs, images mises à l'échelle, particules.
- OffscreenCanvas de worker : dessin ou simulation lourde qui entre en compétition avec le thread d'entrée/principal.
LECTURE OBLIGATOIRE : avant d'optimiser l'animation, les grandes scènes, les particules, les graphiques, la mise à l'échelle des images, la sortie haute DPI ou le rendu de worker, lisez references/performance.md. Ne chargez PAS library-selection à moins d'ajouter/remplacer une bibliothèque.
Condition de sortie : écrivez le pipeline d'images dans l'ordre : échantillonnage d'entrée -> mise à jour -> stratégie d'effacement/redessin -> dessin -> planification de l'image suivante.
Phase 4 - Appliquer les bonnes pratiques canvas
Dimensionnez le canvas par le backing store, pas seulement le CSS. Pour une sortie nette, définissez la taille CSS séparément, définissez canvas.width/height = cssSize * devicePixelRatio, puis normalisez les transformations avec ctx.setTransform(dpr, 0, 0, dpr, 0, 0). Abaissez intentionnellement le DPR pour les scènes gourmandes en performances.
Initialisez le contexte avec des options qui correspondent à la scène. Utilisez { alpha: false } pour les canvas opaques. Utilisez willReadFrequently: true uniquement pour les lectures fréquentes de getImageData, car cela peut modifier la stratégie de backing.
Pour l'entrée, convertissez les coordonnées du pointeur via getBoundingClientRect() et l'échelle du canvas. Ne faites pas confiance à clientX/clientY comme coordonnées du canvas.
Pour l'accessibilité, les canvas décoratifs reçoivent aria-hidden="true" et aucun gestionnaire interactif. Les interactions significatives sur canvas nécessitent des contrôles DOM, des chemins clavier, une gestion du focus, des étiquettes ou une représentation équivalente non-canvas.
Condition de sortie : le redimensionnement, le DPR, les options de contexte, le mappage des coordonnées d'événement, la préférence de mouvement et le démontage sont tous explicites.
Phase 5 - Revoir et vérifier
Révisez le code canvas comme une boucle chaude plus un cycle de vie des ressources. Ne vous arrêtez pas à l'exactitude visuelle.
LECTURE OBLIGATOIRE : lors de la revue de code canvas existant ou avant de finaliser une nouvelle implémentation, lisez references/review-checklist.md. Ne chargez PAS library-selection à moins que la revue n'inclue l'adéquation de la dépendance.
Vérifiez avec au moins un signal d'exécution approprié à la tâche : panneau Performance de Chrome, compteur FPS, instantané mémoire, latence d'interaction, chemin de mouvement réduit, comportement sur onglet caché ou limitation bas de gamme/mobile.
Exemples
- L'utilisateur demande "crée un fond de particules" : classifiez comme animation décorative, rejetez DOM/SVG uniquement si le nombre de particules ou le dessin procédural justifie le canvas, puis lisez
references/visual-quality.mdpour le rendu etreferences/performance.mdpour la boucle. - L'utilisateur demande "construis des formes déplaçables avec sélection" : classifiez comme outil interactif, lisez
references/library-selection.md, choisissez probablement Konva/Paper.js/Canvas 2D brut selon le modèle d'objet. - L'utilisateur demande "revise cette boucle canvas" : classifiez la charge de travail existante, lisez
references/review-checklist.md, et lisezreferences/performance.mduniquement si des problèmes de saccade, de nombre d'objets élevé ou de chemin chaud apparaissent. - L'utilisateur demande "ajoute un croquis p5" : lisez
references/library-selection.md, vérifiez la documentation p5 actuelle avant le code API, puis gardez les frontières du cycle de vie du framework explicites.
JAMAIS
-
JAMAIS redimensionner uniquement avec le CSS pour un canvas dessiné À la place : définissez délibérément les dimensions du backing store et les dimensions CSS ; appliquez la transformation DPR une fois après le redimensionnement. Pourquoi : la mise à l'échelle CSS seule brouille la sortie et cache une incompatibilité de backing store qui s'aggrave sur les écrans Retina.
-
JAMAIS démarrer une boucle RAF sans chemin de démontage À la place : stockez l'ID d'image, annulez le démontage/dispose, et protégez contre les doubles démarrages après les changements de visibilité ou de media-query. Pourquoi : les boucles orphelines continuent de dessiner des canvas détachés et créent des fuites mémoire/CPU que les instantanés attribuent souvent à tort aux composants internes du navigateur.
-
JAMAIS redessiner du contenu statique coûteux à chaque image simplement parce qu'il fait visuellement partie de la scène À la place : mettez-le en cache dans un canvas hors écran, un bitmap d'image, un canvas de couche, un Path2D, ou un cache de forme de bibliothèque. Pourquoi : canvas est en mode immédiat ; les visuels inchangés coûtent toujours le temps de dessin complet à moins d'être explicitement mis en cache ou en couches.
-
JAMAIS utiliser une interaction uniquement canvas comme seul contrôle accessible À la place : fournissez des contrôles/sémantiques DOM ou un modèle d'objet retenu actionnable au clavier avec des étiquettes et un comportement de focus. Pourquoi : les pixels du canvas n'exposent pas les rôles, noms, états ni cibles de hit aux technologies d'assistance.
-
JAMAIS déplacer le travail canvas vers OffscreenCanvas simplement parce que les performances sont médiocres À la place : identifiez d'abord si le goulot d'étranglement est les appels de dessin, le churn d'état, le surdessin, la mise à l'échelle des images, les lectures de pixels ou la simulation ; utilisez les workers lorsque la contention du thread principal est le problème. Pourquoi : les workers ajoutent des contraintes de transfert, de bundling et d'accès DOM ; ils ne corrigent pas une mauvaise architecture de dessin.
-
JAMAIS traiter les règles de performance des bibliothèques à mode retenu comme optionnelles À la place : désactivez l'écoute sur les couches inertes, mettez en cache les formes coûteuses, minimisez le nombre de couches, et détruisez les nœuds/scènes via le cycle de vie de la bibliothèque. Pourquoi : les bibliothèques ajoutent un graphe de scène et une machinerie d'événements ; ignorer leurs commutateurs peut être plus lent que le canvas brut.