Maîtrisez l'API Canvas 2D pour dessiner formes, images, gradients et animations. Guide complet avec 15+ exemples pratiques et explications progressives.
Introduction — la puissance de Canvas en web moderne
Canvas est l'une des technologies les plus puissantes du web moderne. Elle permet de créer des graphiques, des jeux, des animations et des visualisations de données directement dans le navigateur, sans dépendre d'images ou de plugins externes.
La balise <canvas>, introduite en HTML5, crée une surface de dessin bitmap qu'on manipule via JavaScript. Contrairement à SVG (vectoriel), Canvas est raster : une fois dessiné, c'est des pixels.
Cas d'usage typiques :
- Jeux web : 2D et 3D (avec WebGL)
- Graphiques et dashboards : courbes, histogrammes, cartes thermiques
- Animations : bannières animées, intros vidéo
- Photo editing : filtres, retouche
- Visualisations de données : galaxies, simulations physiques
Configuration et contexte 2D
Créer un canvas
<!-- Balise canvas : rectangle de 800x600 pixels -->
<canvas id="myCanvas" width="800" height="600">
<!-- Fallback pour navigateurs ne supportant pas Canvas -->
Canvas n'est pas supporté sur ce navigateur.
</canvas>
Obtenir le contexte 2D
// Récupérer l'élément canvas
const canvas = document.getElementById('myCanvas');
// Obtenir le contexte 2D (c'est le "pinceau")
const ctx = canvas.getContext('2d');
// Maintenant on peut utiliser ctx pour dessiner
ctx.fillStyle = 'blue'; // Couleur de remplissage
ctx.fillRect(50, 50, 200, 100); // Dessiner un carré
Le contexte ctx est votre "pinceau" pour dessiner. C'est via cet objet que vous accédez à toutes les méthodes de dessin.
Dessiner des formes de base — rectangles, cercles, lignes
Rectangles
const ctx = canvas.getContext('2d');
// Carré rempli (bleu)
ctx.fillStyle = 'blue';
ctx.fillRect(50, 50, 100, 100); // x, y, largeur, hauteur
// Carré avec bordure (rouge)
ctx.strokeStyle = 'red';
ctx.lineWidth = 3;
ctx.strokeRect(200, 50, 100, 100);
// Carré vide avec remplissage transparent
ctx.clearRect(300, 50, 100, 100); // Efface une région
Cercles et arcs
// Cercle rempli (vert)
ctx.fillStyle = 'green';
ctx.beginPath();
ctx.arc(100, 150, 50, 0, Math.PI * 2); // x, y, rayon, angleStart, angleEnd
ctx.fill();
// Arc avec bordure
ctx.strokeStyle = 'purple';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(200, 150, 50, 0, Math.PI); // Demi-cercle
ctx.stroke();
// Arc avec lignes droites (secteur)
ctx.beginPath();
ctx.moveTo(350, 150);
ctx.arc(350, 150, 50, 0, Math.PI / 2);
ctx.lineTo(350, 150); // Retour au centre
ctx.fill();
Lignes et polygones
// Triangle (utiliser path)
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.moveTo(50, 200); // Point de départ
ctx.lineTo(150, 200); // Ligne vers ce point
ctx.lineTo(100, 280); // Ligne vers ce point
ctx.lineTo(50, 200); // Fermer le triangle
ctx.stroke(); // Dessiner la bordure
// Remplir le triangle
ctx.fillStyle = 'yellow';
ctx.fill();
// Poly ligne (sans fermeture)
ctx.strokeStyle = 'blue';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(200, 200);
ctx.lineTo(250, 250);
ctx.lineTo(300, 200);
ctx.lineTo(350, 250);
ctx.stroke();
Couleurs, dégradés linéaires et radiaux
Couleurs simples
// Formats valides
ctx.fillStyle = 'red'; // Nom
ctx.fillStyle = '#FF0000'; // Hex
ctx.fillStyle = 'rgb(255, 0, 0)'; // RGB
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; // RGBA avec transparence
ctx.strokeStyle = 'hsl(0, 100%, 50%)'; // HSL
// Transparence globale (affecte tout)
ctx.globalAlpha = 0.5; // 50% transparent
Dégradés linéaires
// Créer un dégradé horizontal
const gradient = ctx.createLinearGradient(0, 0, 200, 0);
gradient.addColorStop(0, 'red'); // 0% = rouge
gradient.addColorStop(0.5, 'yellow'); // 50% = jaune
gradient.addColorStop(1, 'green'); // 100% = vert
// Utiliser le dégradé
ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 200, 100);
Dégradés radiaux
// Dégradé du centre vers l'extérieur
const radialGrad = ctx.createRadialGradient(
100, 100, 10, // Cercle interne : x, y, rayon
100, 100, 100 // Cercle externe : x, y, rayon
);
radialGrad.addColorStop(0, 'white');
radialGrad.addColorStop(1, 'blue');
ctx.fillStyle = radialGrad;
ctx.fillRect(0, 0, 200, 200);
Dessiner et mesurer du texte
Texte simple
// Texte rempli
ctx.font = '30px Arial';
ctx.fillStyle = 'black';
ctx.fillText('Hello Canvas', 50, 50); // texte, x, y
// Texte avec bordure
ctx.strokeStyle = 'red';
ctx.strokeText('Bordure', 50, 100);
// Propriétés de texte
ctx.textAlign = 'center'; // 'left', 'center', 'right'
ctx.textBaseline = 'middle'; // 'top', 'middle', 'bottom'
ctx.font = 'bold 40px "Courier New"';
ctx.fillText('Texte centré', 200, 150);
Mesurer la largeur du texte
const ctx = canvas.getContext('2d');
ctx.font = '30px Arial';
// Connaître la largeur pour centrer
const text = 'Texte';
const metrics = ctx.measureText(text);
const textWidth = metrics.width;
// Centrer horizontalement
const centerX = (canvas.width - textWidth) / 2;
ctx.fillText(text, centerX, 50);
Charger, redimensionner et appliquer des filtres
Dessiner une image
// Créer un objet Image
const img = new Image();
img.src = 'mon-image.jpg';
// Une fois chargée, dessiner
img.onload = () => {
ctx.drawImage(img, 50, 50); // x, y
};
// Attention : les images doivent être chargées avant de dessiner!
// Le code suivant (sans attendre) ne fonctionnera PAS :
// ctx.drawImage(img, 50, 50); // img n'est pas encore chargée!
Redimensionner et recadrer
img.onload = () => {
// Redimensionner
ctx.drawImage(img, 50, 50, 200, 150); // x, y, width, height
// Recadrer une portion de l'image source
ctx.drawImage(
img,
100, 100, 200, 200, // Source : x, y, width, height
400, 50, 200, 200 // Destination : x, y, width, height
);
};
Filtres et effets
// Appliquer un filtre CSS à Canvas (navigateurs modernes)
ctx.filter = 'grayscale(100%)';
ctx.drawImage(img, 50, 50);
// Autres filtres
ctx.filter = 'brightness(1.2) contrast(1.5) blur(2px)';
ctx.drawImage(img, 50, 50);
// Réinitialiser
ctx.filter = 'none';
Transformations et matrices — rotation, échelle, inclinaison
Rotation
ctx.save(); // Sauvegarder l'état
// Déplacer l'origine (point de rotation)
ctx.translate(100, 100);
// Rotation de 45 degrés (en radians)
ctx.rotate(Math.PI / 4);
// Dessiner à l'origine (qui est maintenant 100, 100)
ctx.fillStyle = 'blue';
ctx.fillRect(-25, -25, 50, 50); // Carré centré
ctx.restore(); // Restaurer l'état
Mise à l'échelle
ctx.save();
ctx.translate(150, 150);
ctx.scale(2, 1); // Doubler la largeur, hauteur normale
ctx.fillStyle = 'green';
ctx.fillRect(-25, -25, 50, 50);
ctx.restore();
Inclinaison (skew)
// Canvas n'a pas de méthode skew native, utiliser transform
ctx.save();
ctx.transform(1, 0, 0.5, 1, 100, 100); // Matrice de transformation
ctx.fillStyle = 'red';
ctx.fillRect(0, 0, 100, 100);
ctx.restore();
Animations fluides avec requestAnimationFrame
Boucle d'animation simple
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
let x = 0;
let y = 0;
// Boucle d'animation
function animate() {
// Effacer le canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Mettre à jour la position
x += 2;
y += 1;
// Dessiner au nouvelle position
ctx.fillStyle = 'blue';
ctx.fillRect(x, y, 50, 50);
// Relancer la boucle (60 FPS)
requestAnimationFrame(animate);
}
animate();
Animation circulaire
let angle = 0;
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const radius = 100;
function animateCircle() {
// Effacer
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Calculer la position circulaire
const x = centerX + Math.cos(angle) * radius;
const y = centerY + Math.sin(angle) * radius;
// Dessiner un point
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(x, y, 10, 0, Math.PI * 2);
ctx.fill();
// Incrémenter l'angle
angle += 0.05;
requestAnimationFrame(animateCircle);
}
animateCircle();
Optimisations et bonnes pratiques
Utilisez requestAnimationFrame
// ❌ Mauvais : utilise setInterval (peut causer du jank)
setInterval(() => {
// redraw
}, 16);
// ✅ Bon : utilise requestAnimationFrame (60 FPS fluides)
function animate() {
// redraw
requestAnimationFrame(animate);
}
animate();
Minimisez les redraw
// ❌ Mauvais : redessine la moitié du canvas chaque frame
ctx.clearRect(0, 0, canvas.width / 2, canvas.height);
// ✅ Bon : redessine juste ce qui change
ctx.clearRect(x - 30, y - 30, 100, 100);
ctx.drawImage(sprite, x, y);
Utilisez un canvas caché pour les pré-calculs
// Canvas hors-écran pour les calculs lourds
const offscreenCanvas = document.createElement('canvas');
offscreenCanvas.width = 256;
offscreenCanvas.height = 256;
const offscreenCtx = offscreenCanvas.getContext('2d');
// Pré-calculer une texture complexe une fois
offscreenCtx.fillStyle = 'blue';
offscreenCtx.fillRect(0, 0, 256, 256);
offscreenCtx.strokeStyle = 'red';
offscreenCtx.strokeRect(10, 10, 50, 50);
// Puis, redessiner cette texture sur le canvas principal
const mainCtx = canvas.getContext('2d');
mainCtx.drawImage(offscreenCanvas, 0, 0);
Caching intelligent
// Cacher un rendu coûteux
const cache = {};
function drawComplexShape(key) {
if (cache[key]) {
// Utiliser le cache
ctx.drawImage(cache[key], 50, 50);
} else {
// Créer et mettre en cache
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
// Dessiner la forme complexe
tempCtx.fillStyle = 'purple';
for (let i = 0; i < 1000; i++) {
tempCtx.fillRect(Math.random() * 100, Math.random() * 100, 5, 5);
}
// Mettre en cache
cache[key] = tempCanvas;
// Dessiner
ctx.drawImage(tempCanvas, 50, 50);
}
}
drawComplexShape('shape1');
drawComplexShape('shape1'); // Utilise le cache
Conclusion et cas d'usage réels
Cas d'usage idéaux pour Canvas :
- Jeux web : 2D en particulier (Chess, Flappy Bird, etc.)
- Graphiques temps réel : courbes boursières, cartes thermiques
- Éditeurs graphiques : Paint, Photoshop simplifiés
- Visualisations scientifiques : simulations physiques, fractales
- Générateur d'images : créer des PNG/JPG côté client
Prochaines étapes :
- Explorez WebGL pour les graphiques 3D performantes
- Découvrez les Web Workers pour les calculs lourds en arrière-plan
- Apprenez Three.js ou Babylon.js pour la 3D simplifié
Ressources
- MDN — Canvas API — Documentation officielle avec exemples interactifs et compatibilité navigateurs.
- HTML5 Canvas Tutorials — Tutoriels interactifs progressifs en anglais.
- The Coding Train — Creative Coding — Vidéos et ressources pour la créativité numérique avec Canvas et p5.js.