我正在玩<canvas>
元素,画线等。
我注意到我的对角线是抗锯齿的。我更喜欢看到我正在做的事情 - 有什么方法可以关闭这个功能吗?
答案 0 :(得分:58)
在1-pixel
等坐标上绘制ctx.lineTo(10.5, 10.5)
行。在点(10, 10)
上绘制一个像素的线条意味着该位置的1
像素从9.5
到10.5
,这导致两条线在帆布。
如果你有很多单像素线,并不总是需要将0.5
添加到你想要绘制的实际坐标上的一个好方法是ctx.translate(0.5, 0.5)
你的整个画布在开始。
答案 1 :(得分:47)
对于图片,现在有context.imageSmoothingEnabled
= false
。
然而,没有任何明确控制线条画的东西。您可能需要使用getImageData
和putImageData
绘制自己的行(the hard way)。
答案 2 :(得分:24)
可以在Mozilla Firefox中完成。将其添加到您的代码中:
contextXYZ.mozImageSmoothingEnabled = false;
在Opera中,它目前是一项功能请求,但希望很快就会添加。
答案 3 :(得分:9)
抗锯齿是必需,用于正确绘制涉及非整数坐标(0.4,0.4)的矢量图形,这些坐标除了极少数客户外都会这样做。
当给定非整数坐标时,画布有两个选项:
后一种策略适用于静态图形,但对于小图形(半径为2的圆),曲线将显示清晰的步骤而不是平滑的曲线。
真正的问题是当图形被平移(移动)时 - 一个像素与另一个像素之间的跳跃(1.6 =&gt; 2,1.4 =&gt; 1)意味着形状的原点可能会相对于父容器(不断向上/向下和向左/向右移动1个像素)。
提示#1 :您可以通过缩放画布(例如x)来柔化(或硬化)抗锯齿,然后自己将倒数比例(1 / x)应用于几何体(不使用画布) )。
比较(无缩放):
with(画布比例:0.75;手动比例:1.33):
和(画布比例:1.33;手动比例:0.75):
提示#2 :如果看起来像是一个锯齿状的外观,请尝试几次绘制每个形状(不擦除)。每次绘制时,抗锯齿像素都会变暗。
进行比较。画一次后:
画完三次后:
答案 4 :(得分:8)
我会使用自定义线算法绘制所有内容,例如Bresenham的线算法。看看这个javascript实现: http://members.chello.at/easyfilter/canvas.html
我认为这肯定会解决你的问题。
答案 5 :(得分:6)
我想补充一点,我在缩小图像尺寸和在画布上绘图时遇到了麻烦,它仍然使用平滑处理,即使它在升级时没有使用。
我用这个解决了:
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'))
也许这对某人有用。
答案 6 :(得分:5)
ctx.translate(0.5, 0.5);
ctx.lineWidth = .5;
使用这个组合,我可以绘制漂亮的1px细线。
答案 7 :(得分:5)
试试像 canvas { image-rendering: pixelated; }
这样的东西。
如果您只想让一行不被抗锯齿,这可能不起作用。
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.fillRect(4, 4, 2, 2);
canvas {
image-rendering: pixelated;
width: 100px;
height: 100px; /* Scale 10x */
}
<html>
<head></head>
<body>
<canvas width="10" height="10">Canvas unsupported</canvas>
</body>
</html>
不过我还没有在很多浏览器上测试过。
答案 8 :(得分:4)
请注意一个非常有限的技巧。如果要创建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);
结果将是一个非抗锯齿的黑色&amp;白色图片。这不会是完美的,因为会发生一些抗锯齿,但这种抗锯齿将非常有限,形状的颜色非常像背景的颜色。
答案 9 :(得分:1)
对于那些仍在寻找答案的人。这是我的解决方法。
假设图像为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
答案 10 :(得分:1)
添加:
image-rendering: pixelated; image-rendering: crisp-edges;
canvas 元素的 style 属性有助于在画布上绘制清晰的像素。通过这篇精彩文章发现:
https://developer.mozilla.org/en-US/docs/Games/Techniques/Crisp_pixel_art_look
答案 11 :(得分:1)
我发现了一种使用上下文的 filter
属性禁用路径/形状渲染抗锯齿的更好方法:
ctx = canvas.getContext('2d');
// make canvas context render without antialiasing
ctx.filter = "url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxmaWx0ZXIgaWQ9ImZpbHRlciIgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgY29sb3ItaW50ZXJwb2xhdGlvbi1maWx0ZXJzPSJzUkdCIj48ZmVDb21wb25lbnRUcmFuc2Zlcj48ZmVGdW5jUiB0eXBlPSJpZGVudGl0eSIvPjxmZUZ1bmNHIHR5cGU9ImlkZW50aXR5Ii8+PGZlRnVuY0IgdHlwZT0iaWRlbnRpdHkiLz48ZmVGdW5jQSB0eXBlPSJkaXNjcmV0ZSIgdGFibGVWYWx1ZXM9IjAgMSIvPjwvZmVDb21wb25lbnRUcmFuc2Zlcj48L2ZpbHRlcj48L3N2Zz4=#filter)";
数据 url 是对包含单个过滤器的 SVG 的引用:
<svg xmlns="http://www.w3.org/2000/svg">
<filter id="filter" x="0" y="0" width="100%" height="100%" color-interpolation-filters="sRGB">
<feComponentTransfer>
<feFuncR type="identity"/>
<feFuncG type="identity"/>
<feFuncB type="identity"/>
<feFuncA type="discrete" tableValues="0 1"/>
</feComponentTransfer>
</filter>
</svg>
然后在 url 的最后是对 #filter
的 id 引用:
"url(data:image/svg+...Zz4=#filter)";
SVG 过滤器在 alpha 通道上使用离散变换,渲染时仅在 50% 的边界上选择完全透明或完全不透明。如果需要,可以调整它以添加一些抗锯齿功能,例如:
...
<feFuncA type="discrete" tableValues="0 0 0.25 0.75 1"/>
...
注意,我没有用图像测试这个方法,但我可以假设它会影响图像的半透明部分。我也可以猜测它可能不会阻止对不同颜色边界的图像进行抗锯齿。它不是“最接近的颜色”解决方案,而是二元透明度解决方案。它似乎最适合路径/形状渲染,因为 alpha 是唯一使用路径抗锯齿的通道。
此外,使用最小值为 1 的 lineWidth
是安全的。较细的线条变得稀疏或可能经常完全消失。
答案 12 :(得分:0)
关于StashOfCode答案的两个注意事项:
最好这样做:
描边并填充#FFFFFF
,然后执行以下操作:
imageData.data[i] = (imageData.data[i] >> 7) * 0xFF
这可以解决宽度为1px的行。
除此之外,StashOfCode的解决方案是完美的,因为它不需要编写自己的栅格化函数(不仅要考虑线条,而且还应考虑贝塞尔曲线,圆弧,带有孔的填充多边形等)
答案 13 :(得分:0)
这是Bresenham算法在JavaScript中的基本实现。它基于此维基百科文章中描述的整数算术版本:https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
// File.Copy(@"C:\Users\Asus\Desktop\New.txt", @"D:\New.txt");
string rootFolder = @"D:\";
string authorsFile = "Gym.mdf";
File.Delete(Path.Combine(rootFolder, authorsFile));
string authorsFile2 = "Gym_log.ldf";
File.Delete(Path.Combine(rootFolder, authorsFile2));