出于性能原因,如果可以避免,请不要画圆圈。只需绘制一个宽度和高度为 1 的矩形:
ctx.fillRect(10,10,1,1); // fill in the pixel at (10,10)
如果您打算绘制大量像素,使用画布的图像数据进行像素绘制会效率更高。
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);
}
然后,您可以通过以下方式使用它:
drawPixel(1, 1, 255, 0, 0, 255);
drawPixel(1, 2, 255, 0, 0, 255);
drawPixel(1, 3, 255, 0, 0, 255);
updateCanvas();
有关详细信息,您可以查看此 Mozilla 博客文章:http://hacks.mozilla.org/2009/06/pushing-pixels-with-canvas/
看起来很奇怪,但是 HTML5 支持画线、圆、矩形和许多其他基本形状,它没有任何适合绘制基本点的东西。这样做的唯一方法是用你拥有的任何东西来模拟一个点。
所以基本上有3种可能的解决方案:
将点画成一条线
将点绘制为多边形
将点画成圆
他们每个人都有自己的缺点。
线
function point(x, y, canvas){
canvas.beginPath();
canvas.moveTo(x, y);
canvas.lineTo(x+1, y+1);
canvas.stroke();
}
请记住,我们正在向东南方向绘制,如果这是边缘,则可能会出现问题。但你也可以画在任何其他方向。
长方形
function point(x, y, canvas){
canvas.strokeRect(x,y,1,1);
}
或者以更快的方式使用fillRect,因为渲染引擎只会填充一个像素。
function point(x, y, canvas){
canvas.fillRect(x,y,1,1);
}
圆圈
圆圈的问题之一是引擎更难渲染它们
function point(x, y, canvas){
canvas.beginPath();
canvas.arc(x, y, 1, 0, 2 * Math.PI, true);
canvas.stroke();
}
与使用填充可以实现的矩形相同的想法。
function point(x, y, canvas){
canvas.beginPath();
canvas.arc(x, y, 1, 0, 2 * Math.PI, true);
canvas.fill();
}
所有这些解决方案的问题:
很难跟踪您要绘制的所有点。
当你放大时,它看起来很丑
如果您想知道,绘制点的最佳方式是什么,我会选择填充矩形。你可以看到我的jsperf here with comparison tests
在我的 Firefox 中,这个技巧有效:
function SetPixel(canvas, x, y)
{
canvas.beginPath();
canvas.moveTo(x, y);
canvas.lineTo(x+0.4, y+0.4);
canvas.stroke();
}
小偏移在屏幕上不可见,但会强制渲染引擎实际绘制一个点。
上面声称“如果您打算绘制大量像素,使用画布的图像数据进行像素绘制会更有效”似乎是非常错误的 - 至少对于 Chrome 31.0.1650.57 m 或取决于关于您对“大量像素”的定义。我宁愿直接对相应的帖子发表评论——但不幸的是,我还没有足够的 stackoverflow 点数:
我认为我正在绘制“很多像素”,因此我首先遵循了相应的建议以获得良好的测量结果,后来我将我的实现更改为每个绘制点的简单 ctx.fillRect(..),请参阅 http://www.wothke.ch/webgl_orbittrap/Orbittrap.htm
有趣的是,在我的示例中,愚蠢的 ctx.fillRect() 实现实际上至少是基于 ImageData 的双缓冲方法的两倍。
至少在我的情况下,似乎内置的 ctx.getImageData/ctx.putImageData 实际上慢得令人难以置信。 (知道在基于 ImageData 的方法可能带头之前需要触摸的像素百分比会很有趣..)
结论:如果您需要优化性能,您必须分析您的代码并根据您的发现采取行动。
这应该做的工作
//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();