我想在 Canvas 上四处移动小部件,但出于各种原因我不想使用 sprite。我使用的是最新版本的 Chrome。为了移动小部件,我“取消绘制”它然后在另一个地方重新绘制它。 “取消绘制”是指我只是在同一个地方绘制相同的图像,但使用与背景相同的颜色绘制它,因此在我绘制新图像之前小部件会完全消失。问题是当我“取消绘制”时,原始图像的痕迹仍留在 Canvas 上。我在这里四处寻找相关问题,但没有找到任何有帮助的东西。我理解绘制单像素线和抗锯齿的问题,所以我将线宽设置为 2(以及其他各种非整数值),但无济于事。有人有主意吗?这是一个 fiddle demo ,这是执行更新的函数:
function draw(){
if(previousX !== null) {
ctx.lineWidth = 1;
ctx.fillStyle = '#ffffff';
ctx.strokeStyle = '#ffffff';
drawCircle(previousX, previousY, 20);
}
ctx.lineWidth = 1;
ctx.fillStyle = '#000000';
ctx.strokeStyle = '#000000';
drawCircle(x, y, 20);
console.log('drew circle (' + x + ', ' + y + ')');
previousX = x;
previousY = y;
}
附言我只是一个业余爱好者,在图形方面没有丰富的经验,所以请尽可能简化您的回答。
最佳答案
当你绘制一个带有抗锯齿的形状时,你正在对一些像素进行实心覆盖,但只是对边缘像素进行部分覆盖。麻烦的是像素(暂时忽略液晶面板)是不可分割的单位。那么我们如何部分覆盖像素呢?我们使用 alpha channel 实现这一点。
alpha channel (和 alpha 混合)将圆圈边缘的颜色与圆圈下方的颜色相结合。当圆仅部分覆盖像素时会发生这种情况。这里有一个快速图表来形象化这个问题。
颜色的混合会导致永久性的变化,这种变化无法通过在背景色中再次绘制圆圈来消除。原因:颜色混合再次发生,但这只会导致效果变柔和。
简而言之,重绘只是覆盖了全覆盖的像素。边缘像素不完全是圆的一部分,因此无法掩盖边缘效果。
如果您需要删除圆圈,请考虑恢复原来的圆圈。大概可以复制原来的内容,然后画圆圈,然后当你想移动圆圈的时候,恢复原来的内容,重复这个过程。
This previous SO question可能会给你一些关于复制 Canvas 区域的想法。它使用 drawImage 方法。最好的解决方案是结合使用 getImageData 和 putImageData 方法。我有 modified your Fiddle example向您展示如何做到这一点。你可以试试下面的代码:
var x, y, vx, vy;
var previousX = null, previousY = null;
var data = null;
function draw(){
ctx.lineWidth = 2.5;
ctx.fillStyle = '#000000';
ctx.strokeStyle = '#FF0000';
drawCircle(x, y, 20);
previousX = x;
previousY = y;
}
function drawCircle(x, y, r){
// Step 3: Replace the stuff that was underneath the previous circle
if (data != null)
{
ctx.putImageData(data, previousX - r-5, previousY - r-5);
}
// Step 1: Copy the region in which we intend to draw a circle
data = ctx.getImageData(x - r-5, y - r-5, 2 * r + 10, 2 * r + 10);
// Step 2: Draw the circle
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI*2, true);
ctx.closePath();
ctx.stroke();
ctx.fill();
}
关于javascript - HTML5 : Antialiasing leaves traces when I erase the image,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13896252/