我在玩<canvas>
元素,画线等。
我注意到我的对角线是抗锯齿的。我希望自己的工作看上去比较粗糙-有什么办法可以关闭此功能?
我在玩<canvas>
元素,画线等。
我注意到我的对角线是抗锯齿的。我希望自己的工作看上去比较粗糙-有什么办法可以关闭此功能?
Answers:
对于图像,现在有。context.imageSmoothingEnabled
= false
但是,没有任何东西可以显式控制线条绘制。您可能需要使用和绘制自己的线条(困难的方式)。getImageData
putImageData
putImageData
但它仍然对附近该死的像素产生混淆。
1-pixel
在坐标上绘制线条,例如ctx.lineTo(10.5, 10.5)
。在该点上绘制一条像素线(10, 10)
意味着该1
像素在该位置到达9.5
,10.5
从而在画布上绘制了两条线。
一个很好的技巧是0.5
,如果您有很多单像素线,则不必总是将其添加到要绘制的实际坐标上,这是ctx.translate(0.5, 0.5)
在开始时将其添加到整个画布上。
ctx.translate(0.5,0.5)
没有。在FF39.0上
可以在Mozilla Firefox中完成。将此添加到您的代码:
contextXYZ.mozImageSmoothingEnabled = false;
在Opera中,当前是一项功能请求,但希望很快会添加。
"whether pattern fills and the drawImage() method will attempt to smooth images if their pixels don't line up exactly with the display, when scaling images up"
要正确绘制涉及非整数坐标(0.4,0.4)的矢量图形,需要使用抗锯齿功能,只有很少的客户端会这样做。
给定非整数坐标时,画布具有两个选项:
尽管对于较小的图形(半径为2的圆),曲线将显示清晰的步幅而不是平滑的曲线,但后者将适用于静态图形。
真正的问题是图形被平移(移动)时-一个像素与另一个像素之间的跳转(1.6 => 2、1.4 => 1),这意味着形状的原点可能会相对于父容器跳转(不断移动)上下左右1像素)。
提示1:您可以通过缩放画布(用x表示)来柔化(或强化)抗锯齿,然后自己将倒数比例(1 / x)应用于几何体(不使用画布)。
比较(不缩放):
与(画布比例:0.75;手动比例:1.33):
和(画布比例:1.33;手动比例:0.75):
提示2:如果您确实想要锯齿状的外观,请尝试绘制每种形状几次(不删除)。每次绘制时,抗锯齿像素会变暗。
相比。绘制一次后:
绘制三次后:
我会使用自定义线算法(例如Bresenham的线算法)绘制所有内容。查看以下javascript实现:http : //members.chello.at/easyfilter/canvas.html
我认为这一定会解决您的问题。
setPixel(x, y)
;我这里使用的接受的答案:stackoverflow.com/questions/4899799/...
我想补充一点,在缩小图像和在画布上绘图时遇到了麻烦,尽管在放大时没有使用,但仍在使用平滑。
我解决了使用此:
function setpixelated(context){
context['imageSmoothingEnabled'] = false; /* standard */
context['mozImageSmoothingEnabled'] = false; /* Firefox */
context['oImageSmoothingEnabled'] = false; /* Opera */
context['webkitImageSmoothingEnabled'] = false; /* Safari */
context['msImageSmoothingEnabled'] = false; /* IE */
}
您可以像下面这样使用此功能:
var canvas = document.getElementById('mycanvas')
setpixelated(canvas.getContext('2d'))
也许这对某人有用。
注意一个非常有限的技巧。如果要创建2色图像,则可以在颜色#000000的背景上绘制颜色为#010101的任何形状。完成此操作后,您可以测试imageData.data []中的每个像素,并将其值设置为0xFF,而不是非0x00的值:
imageData = context2d.getImageData (0, 0, g.width, g.height);
for (i = 0; i != imageData.data.length; i ++) {
if (imageData.data[i] != 0x00)
imageData.data[i] = 0xFF;
}
context2d.putImageData (imageData, 0, 0);
结果将是非抗锯齿的黑白图片。由于将进行某些抗锯齿,因此这不是完美的,但是这种抗锯齿将非常有限,形状的颜色与背景的颜色非常相似。
对于那些仍在寻找答案的人。这是我的解决方案。
假设图像为1通道灰色。我只是在ctx.stroke()之后使用了阈值。
ctx.beginPath();
ctx.moveTo(some_x, some_y);
ctx.lineTo(some_x, some_y);
...
ctx.closePath();
ctx.fill();
ctx.stroke();
let image = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height)
for(let x=0; x < ctx.canvas.width; x++) {
for(let y=0; y < ctx.canvas.height; y++) {
if(image.data[x*image.height + y] < 128) {
image.data[x*image.height + y] = 0;
} else {
image.data[x*image.height + y] = 255;
}
}
}
如果您的图像通道是3或4,则需要修改数组索引,例如
x*image.height*number_channel + y*number_channel + channel
关于StashOfCode的答案,只有两个注释:
最好改为这样做:
描边并填充#FFFFFF
,然后执行以下操作:
imageData.data[i] = (imageData.data[i] >> 7) * 0xFF
这就解决了宽度为1px的线。
除此之外,StashOfCode的解决方案是完美的,因为它不需要编写自己的栅格化函数(不仅要考虑线条,还要考虑贝塞尔曲线,圆弧,带孔的填充多边形等)。
这是Bresenham算法在JavaScript中的基本实现。它基于此维基百科文章中描述的整数算术版本:https : //en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
function range(f=0, l) {
var list = [];
const lower = Math.min(f, l);
const higher = Math.max(f, l);
for (var i = lower; i <= higher; i++) {
list.push(i);
}
return list;
}
//Don't ask me.
//https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
function bresenhamLinePoints(start, end) {
let points = [];
if(start.x === end.x) {
return range(f=start.y, l=end.y)
.map(yIdx => {
return {x: start.x, y: yIdx};
});
} else if (start.y === end.y) {
return range(f=start.x, l=end.x)
.map(xIdx => {
return {x: xIdx, y: start.y};
});
}
let dx = Math.abs(end.x - start.x);
let sx = start.x < end.x ? 1 : -1;
let dy = -1*Math.abs(end.y - start.y);
let sy = start.y < end.y ? 1 : - 1;
let err = dx + dy;
let currX = start.x;
let currY = start.y;
while(true) {
points.push({x: currX, y: currY});
if(currX === end.x && currY === end.y) break;
let e2 = 2*err;
if (e2 >= dy) {
err += dy;
currX += sx;
}
if(e2 <= dx) {
err += dx;
currY += sy;
}
}
return points;
}