Dessiner un point sur la canvas HTML5

Dessiner une ligne sur le canevas HTML5 est assez simple en utilisant les fonctions context.moveTo() et context.lineTo() .

Je ne suis pas sûr s’il est possible de dessiner un point, c’est-à-dire de colorer un seul pixel. La fonction lineTo ne dessine pas une seule ligne de pixel (évidemment).

Y a-t-il une méthode pour cela?

Pour des raisons de performance, ne dessinez pas de cercle si vous pouvez l’éviter. Dessinez simplement un rectangle d’une largeur et d’une hauteur de un:

 ctx.fillRect(10,10,1,1); // fill in the pixel at (10,10) 

Si vous prévoyez de dessiner beaucoup de pixels, il est beaucoup plus efficace d’utiliser les données d’image du canevas pour dessiner des pixels.

 var canvas = document.getElementById("myCanvas"); var canvasWidth = canvas.width; var canvasHeight = canvas.height; var ctx = canvas.getContext("2d"); var canvasData = ctx.getImageData(0, 0, canvasWidth, canvasHeight); // That's how you define the value of a pixel // function drawPixel (x, y, r, g, b, a) { var index = (x + y * canvasWidth) * 4; canvasData.data[index + 0] = r; canvasData.data[index + 1] = g; canvasData.data[index + 2] = b; canvasData.data[index + 3] = a; } // That's how you update the canvas, so that your // // modification are taken in consideration // function updateCanvas() { ctx.putImageData(canvasData, 0, 0); } 

Alors vous pouvez l’utiliser de cette façon:

 drawPixel(1, 1, 255, 0, 0, 255); drawPixel(1, 2, 255, 0, 0, 255); drawPixel(1, 3, 255, 0, 0, 255); updateCanvas(); 

Pour plus d’informations, vous pouvez consulter cet article sur le blog Mozilla: http://hacks.mozilla.org/2009/06/pushing-pixels-with-canvas/

Cela semble étrange, mais néanmoins HTML5 prend en charge les lignes de dessin, les cercles, les rectangles et de nombreuses autres formes de base, il n’a rien de approprié pour dessiner le sharepoint base. La seule façon de le faire est de simuler un point avec ce que vous avez.

Donc, fondamentalement, il y a 3 solutions possibles:

  • dessiner le point comme une ligne
  • dessiner le point comme un polygone
  • dessiner le point comme un cercle

Chacun d’eux a ses inconvénients.


Ligne

 function point(x, y, canvas){ canvas.beginPath(); canvas.moveTo(x, y); canvas.lineTo(x+1, y+1); canvas.stroke(); } 

Gardez à l’esprit que nous nous dirigeons vers la direction du sud-est, et si c’est le bord, il peut y avoir un problème. Mais vous pouvez aussi dessiner dans toute autre direction.


Rectangle

 function point(x, y, canvas){ canvas.strokeRect(x,y,1,1); } 

ou de manière plus rapide en utilisant fillRect, car le moteur de rendu ne fera que remplir un pixel.

 function point(x, y, canvas){ canvas.fillRect(x,y,1,1); } 

Cercle

Un des problèmes avec les cercles est qu’il est plus difficile pour un moteur de les rendre

 function point(x, y, canvas){ canvas.beginPath(); canvas.arc(x, y, 1, 0, 2 * Math.PI, true); canvas.stroke(); } 

la même idée qu’avec le rectangle que vous pouvez obtenir avec le remplissage.

 function point(x, y, canvas){ canvas.beginPath(); canvas.arc(x, y, 1, 0, 2 * Math.PI, true); canvas.fill(); } 

Problèmes avec toutes ces solutions:

  • il est difficile de suivre tous les points que vous allez dessiner.
  • quand on fait un zoom avant, ça a l’air moche

Si vous vous demandez quelle est la meilleure façon de dessiner un point , j’irais avec un rectangle plein. Vous pouvez voir mon jsperf ici avec des tests de comparaison

Dans mon Firefox, cette astuce fonctionne:

 function SetPixel(canvas, x, y) { canvas.beginPath(); canvas.moveTo(x, y); canvas.lineTo(x+0.4, y+0.4); canvas.stroke(); } 

Le petit décalage n’est pas visible à l’écran, mais force le moteur de rendu à dessiner un point.

Les affirmations ci-dessus affirment que “Si vous prévoyez de dessiner beaucoup de pixels, il est beaucoup plus efficace d’utiliser les données d’image du canevas pour dessiner des pixels”, semble-t-il – avec Chrome 31.0.1650.57 m ou plus sur votre définition de “lot de pixel”. J’aurais préféré faire un commentaire directement sur le post respectif – mais malheureusement je n’ai pas encore assez de points stackoverflow:

Je pense que je dessine “beaucoup de pixels” et donc j’ai d’abord suivi les conseils respectifs pour une bonne mesure. J’ai ensuite modifié mon implémentation en un simple ctx.fillRect (..) pour chaque sharepointssiné, voir http: // www. wothke.ch/webgl_orbittrap/Orbittrap.htm

Il est intéressant de noter que l’implémentation idiote de ctx.fillRect () dans mon exemple est en fait au moins deux fois plus rapide que l’approche de double mise en mémoire tampon basée sur ImageData.

Au moins pour mon scénario, il semble que ctx.getImageData / ctx.putImageData intégré soit incroyablement lent. (Il serait intéressant de connaître le pourcentage de pixels devant être touchés avant qu’une approche basée sur ImageData puisse prendre la tête ..)

Conclusion: Si vous devez optimiser les performances, vous devez définir votre code et agir sur VOS conclusions.

Cela devrait faire le travail

 //get a reference to the canvas var ctx = $('#canvas')[0].getContext("2d"); //draw a dot ctx.beginPath(); ctx.arc(20, 20, 10, 0, Math.PI*2, true); ctx.closePath(); ctx.fill();