具有模糊线条的画布元素

4
我想知道为什么我的canvas元素的边缘/线条在Chrome,IE和FF中会模糊,并且有所谓的“锯齿效应”(这个表达在英语中存在吗?:-)),如下所示: enter image description here 这只是一个快速的第一次尝试 - 或许我做错了什么? 以下是代码:
c2 = document.getElementById('test').getContext('2d');
c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(0, 0);
c2.lineTo(100, 0);
c2.lineTo(80, 50);
c2.lineTo(0, 50);
c2.closePath();
c2.fill();

c2.fillStyle = "#000";
c2.beginPath();
c2.moveTo(0, 50);
c2.lineTo(80, 50);
c2.lineTo(60, 100);
c2.lineTo(0, 100);
c2.closePath();
c2.fill();

我还将它添加到这个JS Fiddle

2个回答

6
一个canvas对象有两个“大小”:一个是屏幕上的大小,另一个是支持canvas的位图的大小。
你可以通过offsetWidth / offsetHeight或使用css widthheight值(即element.style.widthelement.style.height)来访问第一个大小。相反,第二个大小是在元素本身上指定的<canvas width=100 height=200>或设置element.widthelement.height
如果位图大小小于屏幕大小,则浏览器将使用双线性插值“放大”位图,从而创建模糊效果。
最佳清晰图形可通过将屏幕大小设置为位图大小或仅在使用诸如视网膜显示器之类的设备上,将位图大小设置为屏幕大小的两倍来获得(这是必要的,因为在这些设备上屏幕像素大小被伪造)。
如果您所描述的“模糊”实际上只是抗锯齿,则很抱歉,在绘制画布时没有可移植的方法来禁用抗锯齿,除非通过访问像素数据数组自己绘制像素。
具有适当位图大小的画布以最佳方式呈现,就像svg“矢量图形”一样。以下是一个截图的放大视图,其中包含两条线,一条是在画布上绘制的,另一条来自svg,显然无法区分哪个是哪个。 enter image description here

谢谢你的解释,于是我在这里试着实现它:新的 fiddle。目前为止似乎没有对演示产生影响。我有什么遗漏吗? - ho.s
嗯,在Win7 PC上,Chrome/FF/IE中的模糊问题与以前一样。您提到的另一个“技巧”确实像@markE的答案所示那样有效。因此,我将不得不这样做,或者说...如果边缘真的应该是“完美的”,我想我将不得不绘制一个SVG代替 :-/ - ho.s
@ho.s:一个正确大小的画布与SVG以相同的质量呈现。也许你正在使用缩放显示(例如ctrl +ctrl-)? - 6502
我尝试在这个更新的fiddle中比较了一个svg和一个canvas的对角线-也许是因为盯着它们太久了,我的眼睛有点模糊;-) ..但对我来说,svg线看起来更加“清晰”? - ho.s
我只是无法调整你的示例,对我来说结果是thisone..所以我肯定会选择svg,但非常感谢你的努力。 - ho.s
显示剩余2条评论

3
你可以对画布进行过采样(模拟双倍分辨率):
下图显示了标准分辨率在上方,而“双倍”分辨率在下方:
演示: http://jsfiddle.net/m1erickson/M5NHN/ enter image description here Html:
<canvas id="canvas1" width=300 height=150></canvas>
<canvas id="canvas2" width=600 height=300></canvas>

CSS:

#canvas1 {
    border:1px solid red;
    width:300px;
    height:150px;
}
#canvas2 {
    border:1px solid green;
    width:300px;
    height:150px;
}

JS:

var canvas = document.getElementById("canvas1");
var context1 = canvas.getContext("2d");
var canvas = document.getElementById("canvas2");
var context2 = canvas.getContext("2d");

draw(context1);

context2.scale(2, 2);
draw(context2);

function draw(c2){

c2.fillStyle = '#f00';
c2.beginPath();
c2.moveTo(0, 0);
c2.lineTo(100, 0);
c2.lineTo(80, 50);
c2.lineTo(0, 50);
c2.closePath();
c2.fill();

c2.fillStyle = "#000";
c2.beginPath();
c2.moveTo(0, 50);
c2.lineTo(80, 50);
c2.lineTo(60, 100);
c2.lineTo(0, 100);
c2.closePath();
c2.fill();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接