Dessin sur le Canvas
Apprenez à dessiner sur le canvas HTML avec JavaScript : rectangles, contours, chemins, lignes, cercles et arcs, avec des exemples de code exécutables.
L'élément <canvas> n'est qu'une surface de dessin vierge et transparente. En lui-même, il n'affiche rien — impossible de dessiner dessus avec HTML ou CSS. Tout dessin sur un canvas s'effectue avec JavaScript, via un objet appelé le contexte de rendu. Cette page parcourt les opérations de dessin 2D fondamentales étape par étape : remplissage de rectangles, tracé de contours, dessin de chemins libres, et dessin de cercles et d'arcs.
Si vous n'avez pas encore créé d'élément <canvas>, commencez par la balise HTML <canvas> et l'introduction au Canvas.
Le système de coordonnées du canvas
Chaque méthode de dessin utilise des coordonnées en pixels. La grille du canvas a son origine (0, 0) dans le coin supérieur gauche. L'axe x croît vers la droite et l'axe y croît vers le bas (notez que y augmente quand on descend, contrairement à un graphique mathématique). Ainsi le point (0, 0) correspond au pixel en haut à gauche, et (width, height) au coin inférieur droit.
Pour une étude plus approfondie de la grille, consultez Coordonnées du Canvas.
1. Trouver l'élément canvas
Commencez par obtenir une référence à l'élément <canvas> dans le DOM avec getElementById() :
const canvas = document.getElementById("canvas");2. Obtenir le contexte de rendu 2D
Appelez la méthode getContext() pour obtenir un contexte de dessin. En passant "2d", elle renvoie un objet CanvasRenderingContext2D qui contient toutes les propriétés et méthodes utilisées pour dessiner :
const ctx = canvas.getContext("2d");La variable ctx (abréviation de « context ») est celle sur laquelle vous appelez toutes les commandes de dessin.
getContext() renvoie null si le navigateur ne peut pas fournir le contexte demandé (par exemple, si "2d" est mal orthographié, ou si l'élément n'est pas un vrai <canvas>). Il est conseillé de vérifier ce cas avant de dessiner, afin qu'un contexte manquant échoue silencieusement plutôt que de provoquer une erreur à la ligne suivante :
const ctx = canvas.getContext("2d");
if (!ctx) return; // bail out if the 2D context is unavailable; only valid inside a functionDans un <script> inline ordinaire (qui n'est pas un corps de fonction), enveloppez le dessin dans if (ctx) { ... } à la place, comme le font les exemples ci-dessous.
3. Dessiner un rectangle plein
La propriété fillStyle définit la couleur utilisée pour remplir les formes. Elle peut être n'importe quelle couleur CSS, un motif ou un dégradé :
ctx.fillStyle = "#1c87c9";Ensuite, fillRect(x, y, width, height) dessine un rectangle plein. Les deux premiers paramètres sont les coordonnées x et y du coin supérieur gauche, suivies de la largeur et de la hauteur en pixels :
ctx.fillRect(0, 0, 230, 130);Exemple de dessin d'un rectangle plein :
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="A blue filled rectangle" style="border:1px solid #dddddd;">
Your browser does not support the canvas element.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
// only draw when the 2D context is available
ctx.fillStyle = "#1c87c9";
ctx.fillRect(0, 0, 230, 130);
}
</script>
</body>
</html>Rendre le canvas accessible
Tout ce que vous dessinez sur un canvas n'est que des pixels — il n'a aucune structure, donc les lecteurs d'écran ne peuvent pas le voir. Il n'y a rien à annoncer, et les utilisateurs au clavier ne peuvent rien atteindre à l'intérieur. Donnez aux technologies d'assistance un équivalent textuel de deux façons :
- Le contenu de repli se place entre les balises
<canvas>. Les navigateurs qui restituent le canvas l'ignorent ; les technologies d'assistance (et les très anciens navigateurs) l'utilisent à la place. Mettez-y une description significative, et non « votre navigateur ne prend pas en charge canvas ». role="img"associé àaria-labeldécrit le dessin terminé comme une image unique, de la même façon que le textealtdécrit une balise<img>.
<canvas id="chart" width="250" height="150" role="img"
aria-label="Bar chart: sales doubled from Q1 to Q2.">
A bar chart showing sales doubling from Q1 to Q2.
</canvas>Pour tout élément interactif (zones cliquables, contrôles), fournissez également de vrais éléments DOM focalisables — le canvas seul n'est pas accessible au clavier.
Tracer des contours plutôt que remplir
Parfois vous souhaitez le contour d'une forme plutôt qu'un remplissage plein. Utilisez la propriété strokeStyle pour définir la couleur du contour et strokeRect(x, y, width, height) pour dessiner un rectangle non rempli. La propriété lineWidth contrôle l'épaisseur du contour :
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="A blue rectangular outline" style="border:1px solid #dddddd;">
A rectangle drawn as an outline.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.strokeStyle = "#1c87c9";
ctx.lineWidth = 4;
ctx.strokeRect(20, 20, 200, 100);
}
</script>
</body>
</html>Effacer une partie du canvas
clearRect(x, y, width, height) efface le rectangle donné en le rendant à nouveau totalement transparent. Cette méthode est couramment utilisée pour effacer tout le canvas avant de redessiner (par exemple, à chaque image d'une animation) :
// Erase everything on a 250 × 150 canvas
ctx.clearRect(0, 0, 250, 150);Dans l'exemple suivant, deux rectangles bleus sont dessinés, puis clearRect() perce un trou transparent au milieu du canvas — remarquez que le rectangle de droite est partiellement effacé :
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="Two blue squares with a cleared rectangle cut out of the middle"
style="border:1px solid #dddddd;">
Two filled squares with a cleared region.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.fillStyle = "#1c87c9";
ctx.fillRect(20, 20, 100, 100);
ctx.fillRect(130, 20, 100, 100);
ctx.clearRect(90, 50, 70, 50); // erase a rectangle across both
}
</script>
</body>
</html>Dessiner des chemins (lignes et formes personnalisées)
Les rectangles sont pratiques, mais la plupart des dessins utilisent des chemins — des séquences de points reliés par des lignes ou des courbes. Un chemin se construit avec un petit ensemble de méthodes et n'est pas visible tant que vous n'appelez pas stroke() (pour tracer le contour) ou fill() (pour remplir la zone délimitée).
| Méthode | Ce qu'elle fait |
|---|---|
beginPath() | Démarre un nouveau chemin vide. |
moveTo(x, y) | Déplace le « stylo » en (x, y) sans dessiner. |
lineTo(x, y) | Ajoute une ligne droite du point courant à (x, y). |
closePath() | Trace une ligne de retour vers le point de départ du chemin. |
stroke() | Affiche le chemin sous forme de contour. |
fill() | Remplit la zone délimitée par le chemin. |
Commencez toujours par beginPath()
beginPath() vide la liste des points que le contexte suit actuellement et démarre un chemin vierge. C'est important car le canvas mémorise chaque sous-chemin jusqu'à ce que vous le réinitialisiez. Si vous dessinez une forme, puis ajoutez des points pour une deuxième forme sans appeler beginPath(), les anciens points sont toujours dans le chemin — le prochain stroke() ou fill() redessinera donc aussi la première forme, souvent avec la nouvelle couleur et la nouvelle épaisseur de trait. Le résultat est que les formes « débordent » les unes sur les autres.
Règle générale : appelez beginPath() avant chaque nouvelle forme. Chaque exemple ci-dessous commence ainsi.
Exemple : une ligne simple
Pour dessiner une ligne, commencez un chemin, déplacez-vous vers le point de départ, tracez une ligne jusqu'au point d'arrivée, puis appliquez stroke :
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="A diagonal blue line" style="border:1px solid #dddddd;">
A diagonal line drawn across the canvas.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.beginPath();
ctx.moveTo(20, 20); // start point (x, y)
ctx.lineTo(220, 120); // end point (x, y)
ctx.lineWidth = 3;
ctx.strokeStyle = "#1c87c9";
ctx.stroke(); // make the line visible
}
</script>
</body>
</html>Exemple : un triangle
Enchaîner plusieurs appels à lineTo() crée une forme à plusieurs côtés. closePath() relie le dernier point au premier, et fill() remplit la zone délimitée :
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="A filled green triangle" style="border:1px solid #dddddd;">
A filled green triangle.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.beginPath();
ctx.moveTo(125, 20); // top vertex
ctx.lineTo(220, 130); // bottom-right vertex
ctx.lineTo(30, 130); // bottom-left vertex
ctx.closePath(); // back to the top vertex
ctx.fillStyle = "#8ebf42";
ctx.fill();
}
</script>
</body>
</html>Dessiner des cercles et des arcs
La méthode arc() dessine des cercles et des segments courbes :
ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise);x,y— les coordonnées du centre de l'arc.radius— le rayon en pixels.startAngle,endAngle— les angles de départ et d'arrivée en radians (et non en degrés). L'angle0pointe dans la direction de l'axe x positif — tout droit vers la droite, la direction 3 heures — et par défaut les angles augmentent dans le sens horaire (car l'axe y du canvas est orienté vers le bas). Un cercle complet vaut2 * Math.PIradians.counterclockwise— un boolean optionnel. Passeztruepour aller dans l'autre sens (par défautfalse).
Comme les angles sont en radians, il est pratique de les convertir depuis les degrés grâce à un petit utilitaire :
function toRadians(degrees) {
return degrees * Math.PI / 180;
}
// e.g. a quarter turn:
ctx.arc(125, 75, 50, 0, toRadians(90));Ainsi 90 degrés correspond à Math.PI / 2, 180 degrés à Math.PI, et 360 degrés à 2 * Math.PI.
Un cercle complet va de 0 à 2 * Math.PI. Comme pour tout chemin, vous devez appeler stroke() ou fill() pour le faire apparaître :
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" role="img"
aria-label="A blue filled circle" style="border:1px solid #dddddd;">
A filled blue circle.
</canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
if (ctx) {
ctx.beginPath();
ctx.arc(125, 75, 50, 0, 2 * Math.PI); // center (125,75), radius 50, full circle
ctx.fillStyle = "#1c87c9";
ctx.fill();
}
</script>
</body>
</html>Pour dessiner un demi-cercle à la place, terminez l'arc à Math.PI radians plutôt qu'à 2 * Math.PI.
Pour aller plus loin
Une fois à l'aise avec les formes et les chemins, explorez la suite du tutoriel Canvas :
- Coordonnées du Canvas — la grille en détail.
- Texte sur le Canvas — écrire du texte avec
fillText()etstrokeText(). - Dégradés sur le Canvas — dégradés de couleur linéaires et radiaux.
- Images sur le Canvas — dessiner des images avec
drawImage(). - Référence Canvas — la liste complète des propriétés et méthodes.