<canvas id="myCanvas">Canvas not supported.</canvas> <script type="text/javascript"> var canvas=document.querySelector('#myCanvas'); var ctx=canvas.getContext('2d'); ctx.fillStyle='#FF0000'; ctx.fillRect(0,0,80,100); </script>
<canvas id="myCanvas">
var canvas = document.querySelector("myCanvas");
var ctx = canvas.getContext('2d');
var canvas, ctx, w, h; // en global, pratique... function init() { canvas = document.querySelector("#myCanvas"); w = canvas.width; h = canvas.height; // souvent utiles... ctx = canvas.getContext('2d'); // prêts à travailler ! ... drawMyMonster(); } function drawMyMonster() { ctx.strokeRect(10, 10, 100, 100); // ctx est connu à ce ... // momen-là ! }
<body onload="init();"> ... window.addEventListener("load", init); ... $( document ).ready(function() { init(); }); ... etc.
ctx.strokeRect(0, 0, 100, 00); // dessin immédiat, fil de fer ctx.fillRect(200, 200, 100, 00); // dessin immédiat, plein
ctx.rect(0, 0, 100, 100); ctx.rect( 200, 200, 100, 100); ctx.stroke(); // dessine les deux rectangles en fil de fer ... ctx.stroke(); // attention : dessine à nouveau // le contenu du buffer ! ctx.fill(); // idem en "plein"
ctx.strokeStyle = 'red'; // à partir de maintenant on dessine tout le fil de // fer en rouge ! ctx.strokeRect(200, 200, 100, 100); ctx.strokeRect(10, 10, 100, 100); // Par défaut : noir pour le plein ctx.fillRect(300, 300, 70, 70); ctx.fillStyle = 'green'; ctx.fillRect(310, 310, 50, 50);
On utilise la syntaxe CSS pour les couleurs
ctx.strokeStyle = 'red'; ctx.fillStyle = "#00ff00"; ctx.strokeStyle = "rgb(0, 0, 255)"; ctx.fillStyle = "rgba(0, 0, 255, 0.5)"; // un arrière plan bleu // 50% de transparence
var grd = context.createLinearGradient(0, 0, 300, 0); grd.addColorStop(0, "blue"); grd.addColorStop(0.5, "white"); grd.addColorStop(1, "red"); context.fillStyle = grd;
var grd = context.createLinearGradient(0, 0, 300, 0); // x1, y1, rayon1, x2, y2? rayon2 var grd = context.createRadialGradient(150, 100, 30, 150, 100, 100); grd.addColorStop(0, "red"); grd.addColorStop(0.17, "orange"); ... grd.addColorStop(1, "violet"); context.fillStyle = grd;
// Allocate an image var imageObj = new Image(); imageObj.onload = function(){ var pattern = context.createPattern(imageObj, "repeat"); context.fillStyle = pattern; } imageObj.src = "http://www.dreamstime.com/image.gif";
ctx.strokeRect(x, y, l, h); ctx.fillRect(x, y, l, h); ctx.clearRect(x, y, l, w); // Pour effacer un rectangle ctx.strokeText(msg, x, y); ctx.fillText(msg, x, y); ctx.drawImage(img, x, y); // nombreuses variantes, // étudiées plus loin...
Le reste des formes que l'on peut dessiner est en mode bufférisé, on les appelle des "paths" (chemins).
var imageObj = new Image(); imageObj.onload = function(){ context.drawImage(imageObj, destX, destY); // draw full image but change size context.drawImage(imageObj, destX, destY, width, height); // Draw subpart of source + resize context.drawImage(imageObj,sourceX, sourceY, sourceW,sourceH, destX, destY, destW, destH); }; imageObj.src = "darth-vader.jpg";
beginPath( ) closePath( ) fill( ) stroke( ) clip( ) moveTo(x, y) lineTo(x, y) quadraticCurveTo(cpx, cpy, x, y) bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y) arcTo(x1, y1, x2, y2, radius ) arc(x, y, radius, startAngle, endAngle, anticlockwise) rect(x, y, w, h) isPointInPath(x, y)
context.arc(centreX, centreY, rayon, angleDepart, angleArrivee, sensInverseAiguillesMontre);
Les angles en radians, le dernier paramètre est booléen. True indique qu’on travaille dans le sens inverse des aiguilles d’une montre quand on trace.
Dessiner un cercle bleu clair, centré dans le canvas (sa taille n'est pas connue à l'avance), ayant un contour noir de 5px de large, et une ombre portée,
Dessiner un autre cercle ayant des caractéristiques différentes, les deux doivent êtres sur le même canvas.
Dessiner un demi cercle comme celui-ci, sans utiliser de lineTo
Dessiner une tête avec notamment la bouche et les dents faites avec un ou plusieurs chemins,
On conseille de faire des fonctions dessineNez(), dessineBouche(), etc...
Vous utiliserez ce qui a été vu, notamment : largeur des lignes variables, cercles, arcs de cercles, lignes, etc.
ctx.moveTo(startX, startY); ctx.quadraticCurveTo(controlX, controlY, endX, endY);
ctx.moveTo(startX, startY); ctx.bezierCurveTo(controlX1, controlY1,controlX2, controlY2, endX, endY);
Il est conseillé de sauvegarder le contexte au début d'une fonction de dessin, de le restaurer à la fin...
function drawHead() { // sauvegarde l'état courant du contexte ctx.save(); ctx.shadowColor = "#bbbbbb"; ctx.shadowBlur = 5; ctx.shadowOffsetX = 15; ctx.shadowOffsetY = 15; ctx.lineWidth = 10; ctx.beginPath(); ctx.arc(250, 250, 200, 0, 2*Math.PI); ctx.stroke(); // restore le contexte comme avant l'appel de la fonction ctx.restore(); }
Au lieu de modifier tous les paramètres de tous les appels des fonctions de dessin si on veut déplacer / tourner / retailler un objet complexe, il est plus simple d'utiliser des transformations géométriques.
function drawMonster(x, y, sx, sy, angle) { ctx.save(); // Déplace le repère en x, y, lui applique une rotation et change l'échelle ctx.translate(x, y); ctx.rotate(angle); ctx.scale(sx, sy); drawHead(); drawEyes(); drawMouth(); ctx.restore(); }
function drawRect(x, y, width, height) { ctx.save(); ctx.translate(x, y); ctx.strokeRect(0, 0, width, height); ctx.restore(); }
Va dessiner un rectangle en x, y alors qu'on appelle strokeRect(0, 0, ...) !
Ca fonctionne car c'est tout le repère qui est translaté !
La sauvegarde / restauration du contexte est cruciale ici...
function drawRectangle(x, y, width, height, alphadeg) { var alpharad = alphadeg*2*Math.PI/360; ctx.save(); ctx.translate(x, y); ctx.rotate(alpharad); ctx.strokeRect(0, 0, width, height); ctx.restore(); }
Dessiner un visage en utilisant dans chaque fonction (dessineTete, dessineBouche, dessineYeux, dessineNez) une sauvegarde du contexte suivie de transformations géométriques (translations seulement dans un premier temps). On devra pouvoir déplacer toute la tête d'un coup (les yeux, la bouches, suivront...)
Ajouter maintenant la possibilité de faire tourner la tête sur place, et changer sa taille globale.
Dessiner l'équivalent d'une horloge à aiguille simplifiée (les aiguilles seront des rectangles)...
Si on retaille un canvas on perd son contenu, attention !
JS BinEcrire le contenu d'un canvas comme une image dans un fichier
context.drawImage() peut prendre un autre canvas comme paramètre!
Mais aussi un autre élément video ! Demo!
// Create a pixel Array var imageData = context.createImageData(width, height); // Or grab canvas content as pixels var imageData2 = context.getImageData(x, y, width, height); // do something with the data // modify canvas content context.putImageData(imageData, 0, 0);
Good usage : la librairie JavaScript Pixtatic,
Principe:
function mainLoop(timestamp) { // optional parameter // Draw something ... // Recall 60 times/s itself requestAnimationFrame(mainloop); }