Tips & Tricks (Mis à jour: 02/06/2026)

Développer Canvas avec Claude Code : HiDPI, RAF, events et tests

Créez une interface Canvas fiable avec Claude Code : HiDPI, RAF, Pointer Events, état et Playwright.

Développer Canvas avec Claude Code : HiDPI, RAF, events et tests

Le vrai risque : un beau demo impossible à publier

Canvas est idéal pour dessiner des graphiques personnalisés, des annotations sur image, des particules, des simulations pédagogiques, des mini-jeux ou des visualisations que le DOM classique rend difficilement. Mais Canvas est bas niveau : le navigateur ne conserve pas une structure d’éléments dessinés, ne gère pas automatiquement la densité de pixels et ne sait pas arrêter votre boucle d’animation au bon moment.

Avec Claude Code, la bonne demande n’est donc pas “crée une animation Canvas jolie”. Il faut lui donner les contraintes de production : HiDPI, taille mobile, nettoyage du cycle de vie, Pointer Events, état de dessin, tests Playwright et impact sur les CTA. Dans un article ou une page produit, Canvas cohabite avec le texte, les publicités, les blocs de code et les liens de conversion. S’il crée un scroll horizontal ou repousse le bouton principal, le rendu visuel devient secondaire.

À lire aussi : animation avec Claude Code, Three.js avec Claude Code et visualisation de données avec Claude Code. Références officielles : Claude Code Docs, MDN Canvas API, requestAnimationFrame, Pointer Events et Playwright screenshots.

Le prompt à donner à Claude Code

HiDPI désigne les écrans à forte densité de pixels. Un pixel CSS peut correspondre à plusieurs pixels physiques. Si vous changez seulement la largeur CSS sans ajuster canvas.width et canvas.height, le navigateur agrandit un petit buffer et le résultat devient flou.

Implémente un demo Canvas 2D.
Contraintes:
- Séparer pixels CSS et pixels internes avec devicePixelRatio
- Utiliser requestAnimationFrame et plafonner dt après une pause d'onglet
- Utiliser Pointer Events pour mouse, touch et pen
- Centraliser l'état dans state et garder render(ctx) dédié au dessin
- Utiliser ResizeObserver pour suivre le conteneur
- Éviter tout scroll horizontal à 375px de largeur
- Ajouter des tests Playwright: visibilité, pixels non vides, screenshot, largeur mobile
- Lister fichiers modifiés, risques, cas d'échec et vérifications manuelles

Ce prompt force Claude Code à produire un système de rendu, pas seulement une image animée. C’est le bon niveau de détail pour un composant qui doit rester maintenable.

Architecture simple

Séparez l’entrée, l’état, la mise à jour temporelle, le rendu et la vérification. Ce schéma peut être placé directement dans le contexte envoyé à Claude Code.

Pointer Events
      |
      v
  input handler  --->  state update  --->  update(dt)
                                         |
ResizeObserver ---> resize(dpr)          v
                                     render(ctx)
                                         |
                                         v
                                Playwright checks

render(ctx) ne doit pas enregistrer d’événements, manipuler le DOM ou démarrer une nouvelle boucle. Il lit l’état et dessine. Cette règle rend plus simples undo/redo, gomme, fallback WebGL et tests visuels.

Cas d’usage concrets

Premier cas : les visualisations éditoriales et les dashboards. Canvas fonctionne bien pour les trajectoires en temps réel, les nuages de points denses, les formes libres, les ondes audio et les cartes animées. Claude Code peut écrire la boucle, mais il faut aussi prévoir données vides, chargement, écran mobile et lisibilité du texte autour.

Deuxième cas : les outils d’annotation. Revue de capture, feedback design, correction de cours : lignes, flèches, rectangles, labels et annulation sont fréquents. Pointer Events évite de maintenir trois chemins pour souris, doigt et stylet. Sur les appareils compatibles, pressure peut servir à moduler l’épaisseur.

Troisième cas : l’apprentissage et les jeux légers. Simulations physiques, cartes de vocabulaire, exercices de frappe et particules se prêtent à une mise à jour par frame. Le risque classique est d’oublier d’annuler requestAnimationFrame quand le composant disparaît.

Quatrième cas : les pages produit. Un preview interactif peut aider à comparer, manipuler ou comprendre avant un achat. Il doit soutenir le CTA, pas le masquer.

Exemple exécutable

Ce fragment peut être enregistré dans un fichier HTML et ouvert dans un navigateur. Le point important est ctx.setTransform, qui remplace la transformation après chaque redimensionnement au lieu d’empiler des scale.

<style>
  body { margin: 0; display: grid; min-height: 100vh; place-items: center; background: #111827; }
  canvas { width: min(100%, 720px); aspect-ratio: 16 / 9; display: block; background: #020617; border: 1px solid #374151; border-radius: 8px; touch-action: none; }
</style>
<canvas id="demo" aria-label="Canvas particle demo"></canvas>
<script type="module">
  const canvas = document.querySelector("#demo");
  const ctx = canvas.getContext("2d");
  const state = { width: 1, height: 1, dpr: 1, last: 0, pointer: { x: 0, y: 0, down: false }, dots: [] };

  function resize() {
    const rect = canvas.getBoundingClientRect();
    state.width = Math.max(1, rect.width);
    state.height = Math.max(1, rect.height);
    state.dpr = Math.min(window.devicePixelRatio || 1, 2);
    canvas.width = Math.round(state.width * state.dpr);
    canvas.height = Math.round(state.height * state.dpr);
    ctx.setTransform(state.dpr, 0, 0, state.dpr, 0, 0);
  }

  function point(event) {
    const rect = canvas.getBoundingClientRect();
    return { x: event.clientX - rect.left, y: event.clientY - rect.top, pressure: event.pressure || 0.5 };
  }

  function emit(x, y, pressure = 0.5) {
    for (let i = 0; i < 8; i += 1) {
      const angle = Math.random() * Math.PI * 2;
      const speed = 90 + Math.random() * 180;
      state.dots.push({ x, y, vx: Math.cos(angle) * speed, vy: Math.sin(angle) * speed, life: 1, size: 4 + pressure * 8 });
    }
    state.dots = state.dots.slice(-360);
  }

  canvas.addEventListener("pointerdown", (event) => {
    canvas.setPointerCapture(event.pointerId);
    const p = point(event);
    state.pointer = { x: p.x, y: p.y, down: true };
    emit(p.x, p.y, p.pressure);
  });
  canvas.addEventListener("pointermove", (event) => {
    const events = event.getCoalescedEvents ? event.getCoalescedEvents() : [event];
    for (const item of events) {
      const p = point(item);
      state.pointer.x = p.x;
      state.pointer.y = p.y;
      if (state.pointer.down) emit(p.x, p.y, p.pressure);
    }
  });
  canvas.addEventListener("pointerup", () => (state.pointer.down = false));
  canvas.addEventListener("pointercancel", () => (state.pointer.down = false));

  function frame(now) {
    const dt = state.last ? Math.min((now - state.last) / 1000, 0.033) : 0;
    state.last = now;
    for (const dot of state.dots) {
      dot.vy += 220 * dt;
      dot.x += dot.vx * dt;
      dot.y += dot.vy * dt;
      dot.life -= dt;
    }
    state.dots = state.dots.filter((dot) => dot.life > 0);
    ctx.clearRect(0, 0, state.width, state.height);
    ctx.fillStyle = "#020617";
    ctx.fillRect(0, 0, state.width, state.height);
    for (const dot of state.dots) {
      ctx.fillStyle = `rgba(56,189,248,${dot.life})`;
      ctx.beginPath();
      ctx.arc(dot.x, dot.y, dot.size * dot.life, 0, Math.PI * 2);
      ctx.fill();
    }
    ctx.fillStyle = "#e5e7eb";
    ctx.fillText(`dpr ${state.dpr.toFixed(2)} / dots ${state.dots.length}`, 16, 24);
    requestAnimationFrame(frame);
  }

  new ResizeObserver(resize).observe(canvas);
  resize();
  requestAnimationFrame(frame);
</script>

État, mobile et revue

Canvas n’a pas de noeuds DOM pour les traits dessinés. Pour gérer annulation, outil actif, couleur, largeur de trait ou replay, il faut conserver les points dans un état JavaScript. Demandez à Claude Code d’isoler les transitions d’état dans de petites fonctions et de garder le rendu déterministe.

Sur mobile, les problèmes viennent souvent d’une largeur fixe ou d’une hauteur non définie. width: 800px casse une page de 375px ; width: 100% sans aspect-ratio peut produire un Canvas écrasé. Vérifiez toujours le Canvas avec le texte, les blocs de code, les annonces, les cartes liées et le CTA.

Vérification Playwright

Les assertions DOM ne prouvent pas que le Canvas contient un dessin. Ajoutez visibilité, largeur mobile, pixels peints et screenshot.

import { expect, test } from "@playwright/test";

test("canvas renders on mobile", async ({ page }) => {
  await page.setViewportSize({ width: 390, height: 844 });
  await page.goto("/canvas-demo");
  const canvas = page.locator("canvas").first();
  await expect(canvas).toBeVisible();

  const box = await canvas.boundingBox();
  expect(box?.width ?? 0).toBeLessThanOrEqual(390);

  const paintedPixels = await canvas.evaluate((node) => {
    const context = node.getContext("2d");
    if (!context) return 0;
    const data = context.getImageData(0, 0, node.width, node.height).data;
    let painted = 0;
    for (let i = 3; i < data.length; i += 4) if (data[i] > 0) painted += 1;
    return painted;
  });

  expect(paintedPixels).toBeGreaterThan(1000);
  await expect(canvas).toHaveScreenshot("canvas-mobile.png", { maxDiffPixelRatio: 0.03 });
});

Pièges et monétisation

Les pièges les plus fréquents sont : redimensionner seulement en CSS, empiler ctx.scale, écouter uniquement mousemove, oublier d’annuler la boucle RAF, publier un Canvas à largeur fixe et considérer un screenshot noir comme un succès. Ajoutez ces points à la revue demandée à Claude Code.

Canvas aide la monétisation lorsqu’il explique mieux qu’une image statique : tutoriel interactif, outil d’annotation, aperçu produit ou visualisation liée à une offre. Il nuit à la conversion s’il cache le texte ou repousse l’action suivante. Pour transformer cette approche en workflow d’équipe, la page formation et conseil Claude Code peut servir à cadrer prompts, règles de code et vérifications Playwright.

Après test de cette méthode, le meilleur gain a été la seconde passe de Claude Code dédiée aux échecs. Elle a repéré largeur fixe, ctx.scale cumulatif, entrée tactile oubliée et scroll mobile avant publication. Le demo était moins spectaculaire, mais bien plus fiable pour une vraie page.

#Claude Code #Canvas #WebGL #graphiques #TypeScript
Gratuit

PDF gratuit: cheatsheet Claude Code

Saisissez votre email et téléchargez une page avec commandes, habitudes de review et workflow sûr.

Nous protégeons vos données et n'envoyons pas de spam.

Masa

À propos de l'auteur

Masa

Ingénieur spécialisé dans les workflows pratiques avec Claude Code.