2016-05-31 69 views
1

我画了一些矩形,然后擦除并重画它们以模拟右边的移动 。然而,画布抗锯齿使他们留下痕迹,我不想重画整个画布。 Here's what I'm talking about如何撤消画布反锯齿?

这里是该代码:

var canvas = document.getElementById("canvas"); 
canvas.width = 800; 
canvas.height = 600; 
var context = canvas.getContext("2d"); 
maxFps = 15; 


function loop(x) { 
    setTimeout(function() { 
     undoRect(x); 
     drawRect(x + 30); 
     loop(x + 30); 
    }, 1000/maxFps); 
}; 


function undoRect(x) { 
    context.clearRect(x, 0, 30, 30); 
}; 


function drawRect(x) { 
    context.fillStyle = 'black'; 
    context.fillRect(x, 0, 30, 30); 
}; 

loop(0); 

到目前为止,我试图清除比我画一个更大的矩形,但似乎并没有工作。

+0

我没试过你的代码,但是从只有快速阅读,你似乎只是清楚你在最后一帧画的位置。你为什么不清除整个画布? – Kaiido

+0

@Kaiido,有时候,画布教程过分强调清除画布最小“脏”部分的性能优势。 – markE

+0

@markE,因为清除整个画布并不意味着(同样多)反锯齿计算,我不知道是否有任何性能优势,而且我也不确定是否应该让提问者在这里遵循这些方法,我的意思是,大多数教程都是由读过SO Q/A的人编写的;-) – Kaiido

回答

0

Here's why that's happening.

以下是如何解决这个问题:

var canvas = document.getElementById("canvas"); 
 
canvas.width = 800; 
 
canvas.height = 600; 
 

 
var context = canvas.getContext("2d"); 
 
maxFps = 15; 
 

 

 
function loop(x) { 
 
    setTimeout(function() { 
 
    undoRect(x); 
 
    drawRect(x + 30); 
 
    loop(x + 30); 
 
    }, 1000/maxFps); 
 
}; 
 

 

 
function undoRect(x) { 
 
    context.clearRect(x, 0, 30, 30); 
 
}; 
 

 

 
function drawRect(x) { 
 
    context.fillStyle = 'black'; 
 
    context.fillRect(x, 0, 30, 30); 
 
}; 
 

 
loop(0.5); // boop
<canvas id="canvas"></canvas>

通过0.5px抵消你的矩形。

+0

这似乎并不奏效。 –

+0

@MetaXenology适合我。你使用的是什么浏览器? –

+0

铬。尽管如此,它也会在Firefox上留下痕迹。 –

0

不幸的是,在画布上绘图时,没有可移植的方式来关闭消除锯齿功能。例如,如果要绘制两个共享边的半透明多边形,可能会产生问题,因为边界像素将无法正确处理(在每个基元的基础上进行工作时,无法正确进行抗锯齿......完全正确抗锯齿在一般情况下需要全场处理)。

但是,如果您只需要绘制矩形,则可以通过使用坐标来获得像素精确的结果,例如在使用大小为1px的笔进行绘制时,该坐标为int + 0.5

当绘制填充rects与fillRect坐标不需要调整:

<!DOCTYPE html> 
 
<html> 
 

 
<body> 
 
    <canvas id="canvas"></canvas> 
 
    <script> 
 
    var x = 0; 
 
    setInterval(function() { 
 
     var canvas = document.getElementById("canvas"); 
 
     var ctx = canvas.getContext("2d"); 
 
     ctx.clearRect(x, 0, 30, 30); 
 
     x += 10; 
 
     ctx.fillStyle = "#F00"; 
 
     ctx.fillRect(x, 0, 30, 30); 
 
    }, 100); 
 
    </script> 
 
</body> 
 

 
</html>

另一种选择是只使用多个重叠画布动画代替绘图/擦除一个画布上(画布像素默认是透明的,画布上的每原始反锯齿正确更新边缘的透明度)。

+0

@帕特里克罗伯特的答案使用0.5技巧,但似乎没有工作。你有解释吗?使用大小为1px的笔画出水平或垂直线时,需要使用 –

+1

+0.5。 'fillRect'不需要调整。 – 6502

2

显示的代码没有问题。 fillRect()clearRect()不需要抵消以避免被消除锯齿。

该问题表明在程序的早期版本中已应用偏移量,或者浏览器存在当前问题。

确保变换运行循环之前复位:如下图所示然而

ctx.setTransform(1,0,0,1,0,0); // identity matrix 
// start loop 

如果仍然出现问题,那么你应该报告此为铬/ Mozilla浏览器中的错误,这是不是一个问题在更新的版本中。您也可以考虑清除边界框每个方向+1像素,可选地,清除整个画布并重绘。

这里是屏幕记录结果(点击图片看100%) -

火狐(V47。0b9)

Firefox

铬(V52金丝雀)

Chrome

无道(fiddle for test