W3docs

Introduction à Canvas

Découvrez l'élément HTML <canvas> : système de coordonnées, contexte de rendu 2D, mise à l'échelle haute résolution, accessibilité et exemples.

L'élément HTML <canvas> est une surface de dessin rectangulaire que vous contrôlez entièrement par script. L'élément lui-même n'est qu'un conteneur vide — il ne dessine rien par lui-même. Vous utilisez JavaScript pour émettre des commandes de dessin qui peignent des pixels dessus.

Cette page présente l'élément <canvas>, son système de coordonnées, le contexte de rendu 2D et les opérations de dessin les plus courantes : formes, texte, dégradés, lignes et images.

Qu'est-ce que l'élément <canvas> ?

<canvas> vous fournit un bitmap — une grille de pixels dans laquelle vous dessinez immédiatement. Une fois qu'une forme est peinte, le canvas ne la mémorise pas en tant qu'objet ; ce ne sont que des pixels colorés. C'est la différence fondamentale avec SVG, où chaque forme reste un nœud du DOM que vous pouvez re-styliser ou animer individuellement.

Ce compromis guide le choix entre les deux :

  • Choisissez <canvas> pour un contrôle au niveau du pixel, des milliers d'objets, une animation image par image rapide, des jeux, du traitement d'images, des graphiques avec beaucoup de données ou des effets de particules. Étant en mode « immédiat », le redessin est peu coûteux.
  • Choisissez SVG lorsque vous avez besoin de vecteurs indépendants de la résolution, d'icônes évolutives, d'un nombre gérable de formes que vous souhaitez inspecter, cliquer ou animer via CSS/DOM.
  • Choisissez CSS pour la mise en page, les transitions et les effets sur les éléments HTML ordinaires — pas pour le dessin libre.
Astuce

Vous pouvez placer plusieurs éléments <canvas> sur la même page HTML, chacun avec son propre contexte.

Le système de coordonnées

Un canvas utilise une grille de coordonnées 2D. L'origine (0, 0) se trouve dans le coin supérieur gauche. L'axe x augmente vers la droite et l'axe y augmente vers le bas — notez que y croît vers le bas, à l'opposé d'un graphique mathématique. Un point (100, 60) est donc à 100 pixels du bord gauche et à 60 pixels du haut.

La zone de dessin est définie par les attributs width et height (en pixels CSS) :

<canvas id="canvas" width="250" height="150"></canvas>
Danger

Définissez la taille du canvas avec les attributs width et height, et non avec CSS. Les propriétés CSS width/height ne font qu'étirer le bitmap existant, ce qui floute votre dessin. Ajoutez une bordure avec l'attribut style ou une classe.

Le contexte de rendu 2D

Vous ne dessinez jamais directement sur l'élément <canvas> — vous dessinez via un contexte de rendu, un objet qui expose l'API de dessin. Vous l'obtenez avec getContext() :

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

getContext('2d') retourne un CanvasRenderingContext2D, qui contient toutes les méthodes et propriétés utilisées ci-dessous (fillRect, arc, fillText, strokeStyle, etc.). C'est le point de départ idéal pour presque tout dessin 2D.

D'autres types de contexte existent pour des besoins différents :

  • 'webgl' / 'webgl2' — 3D accélérée par GPU (et 2D haute performance) via l'API OpenGL ES.
  • 'bitmaprenderer' — affiche un ImageBitmap sans API de dessin propre.

Ce chapitre utilise uniquement le contexte '2d'.

Accessibilité : contenu de secours

Tout ce que vous placez entre les balises ouvrante et fermante de <canvas> constitue du contenu de secours. Les navigateurs qui prennent en charge canvas l'ignorent ; les navigateurs (ou technologies d'assistance) qui ne peuvent pas afficher le canvas le montrent à la place. Comme les pixels dessinés sont invisibles pour les lecteurs d'écran, utilisez cet espace pour décrire le graphique, ou ajoutez un aria-label / role afin que le canvas soit annoncé de manière significative.

<canvas id="canvas" width="250" height="150" role="img" aria-label="A blue circle on a white background">
  A blue circle on a white background.
</canvas>

Pour les canvas interactifs (jeux, applications de dessin), fournissez de véritables contrôles HTML focusables à l'intérieur de l'élément comme solution de secours, car les pixels eux-mêmes ne peuvent pas recevoir le focus via la touche Tab.

Exemple de la balise HTML <canvas> :

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <canvas id="canvas" width="250" height="150" style="border:1px solid #1c87c9;">
      The HTML5 canvas tag is not supported by your browser.
    </canvas>
  </body>
</html>

Exemple de la balise HTML <canvas> pour dessiner un cercle :

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <canvas id="exampleCanvas" width="200" height="200" style="border:1px solid #dddddd;">
      HTML5 canvas tag is not supported by your browser.
    </canvas>
    <script>
      const c = document.getElementById("exampleCanvas");
      const ctx = c.getContext("2d");
      ctx.beginPath();
      ctx.arc(100, 100, 60, 0, 2 * Math.PI);
      ctx.strokeStyle = '#009299';
      ctx.stroke();
    </script>
  </body>
</html>

La méthode arc() prend cinq arguments : arc(x, y, radius, startAngle, endAngle). Ici (100, 100) est le centre du cercle, 60 est le rayon en pixels, et l'arc balaie de l'angle 0 à 2 * Math.PI. Les angles sont mesurés en radians, et un cercle complet vaut radians, donc de 0 à 2 * Math.PI trace le cercle entier. beginPath() commence un nouveau tracé, et stroke() le contourne en utilisant le strokeStyle courant. Pour le remplir à la place, définissez fillStyle et appelez fill(). En savoir plus dans Canvas drawing et Canvas coordinates.

Exemple de la balise HTML <canvas> pour écrire du texte :

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <canvas id="exampleCanvas" width="350" height="110" style="border:1px solid #dddddd;">
      HTML5 canvas tag is not supported by your browser.
    </canvas>
    <script>
      const c = document.getElementById("exampleCanvas");
      const ctx = c.getContext("2d");
      ctx.font = "40px Arial";
      ctx.fillStyle = '#262ac7';
      ctx.fillText("Canvas Text", 55, 65);
    </script>
  </body>
</html>

fillText(text, x, y) peint du texte rempli aux coordonnées données. La propriété font utilise la syntaxe abrégée CSS standard pour les polices. Voir Canvas text pour l'alignement, le contour du texte et la mesure de la largeur.

Exemple de la balise HTML <canvas> pour dessiner un dégradé linéaire :

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <canvas id="exampleCanvas" width="300" height="140" style="border:1px solid #dddddd;">
      The HTML5 canvas tag is not supported by your browser.
    </canvas>
    <script>
      const c = document.getElementById("exampleCanvas");
      const ctx = c.getContext("2d");
      const grd = ctx.createLinearGradient(0, 0, 300, 0);
      grd.addColorStop(0, "#359900");
      grd.addColorStop(1, "#ffffff");
      ctx.fillStyle = grd;
      ctx.fillRect(20, 20, 250, 100);
    </script>
  </body>
</html>

createLinearGradient(x0, y0, x1, y1) définit la direction du dégradé par deux points. Ici (0, 0) à (300, 0) est un dégradé horizontal de gauche à droite. addColorStop(offset, color) place une couleur à une position allant de 0 (début) à 1 (fin), le vert s'estompant ainsi en blanc. L'attribution du dégradé à fillStyle fait que fillRect(x, y, width, height) peint avec celui-ci. Plus d'informations dans Canvas gradients.

Exemple de la balise HTML <canvas> pour dessiner une ligne :

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <canvas id="exampleCanvas" width="150" height="150" style="border:1px solid #cccccc;">
      The HTML5 canvas tag is not supported by your browser.
    </canvas>
    <script>
      const c = document.getElementById("exampleCanvas");
      const ctx = c.getContext("2d");
      ctx.moveTo(0, 0);
      ctx.lineTo(150, 150);
      ctx.strokeStyle = '#86417d';
      ctx.stroke();
    </script>
  </body>
</html>

moveTo(x, y) lève le « stylo » jusqu'à un point de départ sans dessiner, et lineTo(x, y) ajoute un segment droit jusqu'à ce point. Rien n'apparaît tant que vous n'appelez pas stroke(). Voir Canvas drawing pour les tracés multi-segments, l'épaisseur de ligne et les jonctions.

Exemple de la balise HTML <canvas> pour dessiner une image :

Pour rester autonome (et éviter les problèmes d'origine croisée — voir la note ci-dessous), cet exemple utilise une petite image SVG intégrée comme URI de données plutôt qu'une photo distante :

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <h2>Draw an image with canvas</h2>
    <canvas id="exampleCanvas" width="220" height="120" style="border:1px solid #dddddd;"></canvas>
    <script>
      const canvas = document.getElementById('exampleCanvas');
      const ctx = canvas.getContext('2d');
      const image = new Image();
      image.addEventListener('load', () => {
        // drawImage(image, dx, dy) draws at the given top-left position
        ctx.drawImage(image, 10, 10);
        // Scaled copy: drawImage(image, dx, dy, dWidth, dHeight)
        ctx.drawImage(image, 120, 10, 50, 50);
      });
      image.src =
        "data:image/svg+xml," +
        encodeURIComponent(
          '<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">' +
          '<circle cx="50" cy="50" r="45" fill="#1c87c9" /></svg>'
        );
    </script>
  </body>
</html>

drawImage() accepte trois formes : drawImage(image, dx, dy), drawImage(image, dx, dy, dWidth, dHeight) pour mettre à l'échelle, et drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) pour recadrer un rectangle source (s*) et le placer dans un rectangle de destination (d*). Dessinez toujours à l'intérieur de l'événement load de l'image afin que les pixels soient prêts. Voir Canvas images pour en savoir plus.

Danger

Piège CORS. Dessiner une image provenant d'une autre origine sans les en-têtes CORS appropriés « souille » le canvas. Après cela, getImageData() et toDataURL() lèvent une erreur de sécurité. Si vous devez relire les pixels d'une image distante, celle-ci doit être servie avec des en-têtes CORS permissifs et chargée avec image.crossOrigin = "anonymous" avant de définir src.

Exemple de la balise HTML <canvas> pour dessiner un dégradé circulaire :

<!DOCTYPE html>
<html>
  <head>
    <title>Title of the document</title>
  </head>
  <body>
    <canvas id="exampleCanvas" width="260" height="160" style="border:1px solid #cdcdcd;">
      The HTML5 canvas tag is not supported by your browser.
    </canvas>
    <script>
      const c = document.getElementById("exampleCanvas");
      const ctx = c.getContext("2d");
      const grd = ctx.createRadialGradient(150, 75, 10, 115, 90, 150);
      grd.addColorStop(0, "purple");
      grd.addColorStop(1, "white");
      ctx.fillStyle = grd;
      ctx.fillRect(20, 20, 220, 120);
    </script>
  </body>
</html>

createRadialGradient(x0, y0, r0, x1, y1, r1) réalise un fondu entre deux cercles : un cercle de départ (centre (150, 75), rayon 10) et un cercle de fin (centre (115, 90), rayon 150). Les arrêts de couleur passent du violet au niveau du cercle intérieur au blanc au niveau du cercle extérieur, produisant l'effet de halo arrondi. Comparez avec createLinearGradient ci-dessus et lisez-en davantage dans Canvas gradients.

Affichages haute densité (Retina)

Sur les écrans haute densité, un pixel CSS correspond à plusieurs pixels physiques. Un canvas dimensionné uniquement en pixels CSS apparaît donc flou sur ces affichages. La solution consiste à mettre à l'échelle le bitmap par window.devicePixelRatio, puis à mettre à l'échelle le contexte afin que vos coordonnées de dessin restent identiques :

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const ratio = window.devicePixelRatio || 1;

// CSS size (layout) stays the same:
const cssWidth = 250;
const cssHeight = 150;
canvas.style.width = cssWidth + 'px';
canvas.style.height = cssHeight + 'px';

// Backing bitmap gets more device pixels:
canvas.width = cssWidth * ratio;
canvas.height = cssHeight * ratio;

// Scale once so you keep drawing in CSS-pixel coordinates:
ctx.scale(ratio, ratio);

Après cela, dessiner arc(100, 100, 60, …) produit un cercle net aussi bien sur les écrans standard que Retina.

Chapitres associés

Pratique

Pratique
Quelles sont les caractéristiques et l'utilisation de HTML Canvas ?
Quelles sont les caractéristiques et l'utilisation de HTML Canvas ?
Was this page helpful?