Visit Mozilla.org

Tutoriel canvas:Compositions

Un article de MDC.

Sommaire

Dans tous les exemples précédents, nous avons toujours dessiné des formes les unes au dessus des autres. C'est plus qu'il n'en faut pour la plupart des situations. Cela nous limite par exemple dans la façon dont les formes composées peuvent être construites. Cependant, on peut changer ce comportement en définissant la propriété globalCompositeOperation.

[modifier] globalCompositeOperation

Il est non seulement possible de dessiner de nouvelles formes derrière des formes existantes, mais également les utiliser pour masquer certaines zones, effacer certaines parties du canevas (pas seulement des rectangles comme le fait la méthode clearRect) et bien plus.

globalCompositeOperation = type

type est une chaîne représentant l'une des douze opérations de composition. Chacun des types disponibles est décrit ci-dessous.

Note : Dans tous les exemples ci-dessous, le carré bleu est dessiné en premier et est appelé le contenu existant du canevas. Le cercle rouge est dessiné ensuite est est appelé une nouvelle forme.

source-over (default)
Il s'agit du réglage par défaut. Dessine les nouvelles formes par dessus le contenu existant du canevas.

Image:Canvas_composite_srcovr.png

destination-over
Les nouvelles formes sont dessinées derrière le contenu existant du canevas.

Image:Canvas_composite_destovr.png

source-in
La nouvelle forme est dessinée seulement lorsqu'elle se superpose au canevas de destination. Tout le reste est rendu transparent.

Image:Canvas_composite_srcin.png

destination-in
Le contenu existant du canevas est conservé là où la nouvelle forme et le contenu existant se superposent. Tout le reste est rendu transparent.

Image:Canvas_composite_destin.png

source-out
La nouvelle forme est dessinée là où elle ne se superpose pas au contenu existant du canevas.

Image:Canvas_composite_srcout.png

destination-out
Le contenu existant est conservé là où il ne se superpose pas à la nouvelle forme.

Image:Canvas_composite_destout.png

source-atop
La nouvelle forme est uniquement dessinée là où elle se superpose au contenu existant du canevas.

Image:Canvas_composite_srcatop.png

destination-atop
Le canevas existant est uniquement conservé là où il se superpose à la nouvelle forme. La nouvelle forme est dessinée derrière le contenu du canevas.

Image:Canvas_composite_destatop.png

lighter
Là où les deux formes se superposent, la couleur est déterminée en additionnant les valeurs de couleur.

Image:Canvas_composite_lighten.png

darker
Là où les deux formes se superposent, la couleur est déterminée en soustrayant les valeurs de couleur.

Image:Canvas_composite_darken.png

xor
Les formes sont rendues transparentes là où elles se superposent, et sont dessinées normalement partout ailleurs.

Image:Canvas_composite_xor.png

copy
Dessine uniquement la nouvelle forme et efface tout le reste.

Image:Canvas_composite_copy.png

Note : Actuellement, les réglages copy et darker ne font rien du tout dans les navigateurs basés sur Gecko 1.8 (Firefox 1.5, etc.)

Afficher tous les exemples

[modifier] Chemins de découpe

Un chemin de découpe est comme une forme normale du canevas, mais qui agit comme un masque pour cacher les parties non désirées de l'image. On peut le visualiser dans l'image à droite. L'étoile rouge est notre chemin de découpe. Tout ce qui n'entre pas dans ce chemin ne sera pas dessiné sur le canevas.

Si l'on compare les chemins de découpe à la propriété globalCompositeOperation vue plus haut, les réglages produisant plus ou moins le même effet sont source-in et source-atop. Les différences les plus importantes entre les deux sont que les chemins de découpe ne sont jamais réellement dessinés sur le canevas, et que les cehmins de découpe ne sont pas affectés par l'ajout de nouvelles formes. Ils sont donc idéaux pour dessiner plusieurs formes dans une zone restreinte.

Dans le chapitre à propos du dessin de formes géométriques, nous avions seulement mentionné les méthodes stroke et fill. Il y a cependant une troisième méthode que l'on peut utiliser, et il s'agit de clip.

clip()

La méthode clip est utilisée pour créer un nouveau chemin de découpe. Par défaut, l'élément canvas a un chemin de découpe qui a exactement la même taille que le canevas lui-même (c'est-à-dire qu'aucune découpe n'est faite).

[modifier] Un exemple d'utilisation de clip

Dans cet exemple, on utilise un chemin de découpe circulaire pour restreindre le dessin d'un ensemble d'étoiles dans une région particulière.

Dans les premières lignes de code, un rectangle noir est dessiné de la taille du canevas comme fond, et l'origine est déplacée vers le centre. Ensuite, le chemin de découpe circulaire est créé en dessinant un arc et en appelant la méthode clip. Les chemins de découpe font également partie de l'état du canevas lorsqu'il est enregistré. Si l'on voulait conserver la découpe initiale, on aurait pu enregistrer l'état du canevas avant d'en créer une nouvelle.

Après avoir créé le chemin de découpe, tout ce qui est dessiné par la suite n'apparaîtra qu'à l'intérieur du chemin. C'est clairement visible dans le cas du dégradé radial qui est dessiné ensuite. Après cela, un ensemble d'étoiles positionnées et dimensionnées aléatoirement sont dessinées (à l'aide d'une fonction personnalisée). Encore une fois, les étoiles apparaissent uniquement à l'intérieur du chemin de découpe spécifié.

Afficher cet exemple

function draw() {
  var ctx = document.getElementById('canvas').getContext('2d');
  ctx.fillRect(0, 0, 150, 150);
  ctx.translate(75, 75);

  // Crée un chemin de découpe circulaire
  ctx.beginPath();
  ctx.arc(0, 0, 60, 0, Math.PI*2, true);
  ctx.clip();

  // dessine le fond
  var lingrad = ctx.createLinearGradient(0, -75, 0, 75);
  lingrad.addColorStop(0, '#232256');
  lingrad.addColorStop(1, '#143778');
  
  ctx.fillStyle = lingrad;
  ctx.fillRect(-75, -75, 150, 150);

  // dessine des étoiles
  for (j = 1; j < 50; j++) {
    ctx.save();
    ctx.fillStyle = '#fff';
    ctx.translate(75 - Math.floor(Math.random()*150),
                  75 - Math.floor(Math.random()*150));
    drawStar(ctx, Math.floor(Math.random()*4) + 2);
    ctx.restore();
  }
  
}
function drawStar(ctx, r) {
  ctx.save();
  ctx.beginPath();
  ctx.moveTo(r, 0);
  for (i = 0; i < 9; i++) {
    ctx.rotate(Math.PI/5);
    if (i%2 == 0) {
      ctx.lineTo((r/0.525731)*0.200811, 0);
    } else {
      ctx.lineTo(r, 0);
    }
  }
  ctx.closePath();
  ctx.fill();
  ctx.restore();
}