HTML5 Canvas没有显式设置单个像素的方法。
可以使用非常短的行设置像素,但反字符和行大写可能会干扰。
另一种方法可能是创建一个小的ImageData对象,并使用:
context.putImageData(data, x, y)
把它放在合适的位置。
有人能描述一种高效可靠的方法吗?
HTML5 Canvas没有显式设置单个像素的方法。
可以使用非常短的行设置像素,但反字符和行大写可能会干扰。
另一种方法可能是创建一个小的ImageData对象,并使用:
context.putImageData(data, x, y)
把它放在合适的位置。
有人能描述一种高效可靠的方法吗?
当前回答
如果你担心速度,那么你也可以考虑WebGL。
其他回答
如果你担心速度,那么你也可以考虑WebGL。
这看起来很奇怪,但是HTML5支持画线、圆、矩形和许多其他基本形状,它没有任何适合画基本点的东西。唯一的方法就是用你有的东西来模拟点。
所以基本上有三种可能的解决方案:
画一个点作为一条线 画一个多边形 画一个圆
每一种都有其缺点
Line
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。
一种没有提到的方法是使用getImageData,然后使用putImageData。 这种方法很适合当你想要画很多的时候,快速。 http://next.plnkr.co/edit/mfNyalsAR2MWkccr
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
var id = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
var pixels = id.data;
var x = Math.floor(Math.random() * canvasWidth);
var y = Math.floor(Math.random() * canvasHeight);
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
var off = (y * id.width + x) * 4;
pixels[off] = r;
pixels[off + 1] = g;
pixels[off + 2] = b;
pixels[off + 3] = 255;
ctx.putImageData(id, 0, 0);
像sdleihssirhc说的那样画一个矩形!
ctx.fillRect (10, 10, 1, 1);
^——应该在x:10, y:10处画一个1x1的矩形
快捷方便
下面的类实现了本文中描述的快速方法,并包含了所有您需要的:readPixel, putPixel,获取宽度/高度。类在调用refresh()方法后更新画布。算例求解二维波动方程的简单情形
class Screen{ constructor(canvasSelector) { this.canvas = document.querySelector(canvasSelector); this.width = this.canvas.width; this.height = this.canvas.height; this.ctx = this.canvas.getContext('2d'); this.imageData = this.ctx.getImageData(0, 0, this.width, this.height); this.buf = new ArrayBuffer(this.imageData.data.length); this.buf8 = new Uint8ClampedArray(this.buf); this.data = new Uint32Array(this.buf); } // r,g,b,a - red, gren, blue, alpha components in range 0-255 putPixel(x,y,r,g,b,a=255) { this.data[y * this.width + x] = (a<<24) | (b<<16) | (g<<8) | r; } readPixel(x,y) { let p= this.data[y * this.width + x] return [p&0xff, p>>8&0xff, p>>16&0xff, p>>>24]; } refresh() { this.imageData.data.set(this.buf8); this.ctx.putImageData(this.imageData, 0, 0); } } // -------- // TEST // -------- let s= new Screen('#canvas'); // initialise function draw() { for (var y = 1; y < s.height-1; ++y) { for (var x = 1; x < s.width-1; ++x) { let a = [[1,0],[-1,0],[0,1],[0,-1]].reduce((a,[xp,yp])=> a+= s.readPixel(x+xp,y+yp)[0] // read pixel ,0); let v= a/1.99446-tmp[x][y]; tmp[x][y]=v<0 ? 0:v; } } for (var y = 1; y < s.height-1; ++y) { for (var x = 1; x < s.width-1; ++x) { let v=tmp[x][y]; tmp[x][y]= s.readPixel(x,y)[0]; // read pixel s.putPixel(x,y, v,0,0); // put pixel } } s.refresh(); window.requestAnimationFrame(draw) } // temporary 2d buffer ()for solving wave equation) let tmp = [...Array(s.width)].map(x => Array(s.height).fill(0)); function move(e) { s.putPixel(e.x-10, e.y-10, 255,255,255);} draw(); <canvas id="canvas" height="150" width="512" onmousemove="move(event)"></canvas> <div>Move mouse on black square</div>