javascript - HTML5 : Antialiasing leaves traces when I erase the image

标签 javascript html canvas sprite antialiasing

我想在 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 混合)将圆圈边缘的颜色与圆圈下方的颜色相结合。当圆仅部分覆盖像素时会发生这种情况。这里有一个快速图表来形象化这个问题。

enter image description here

颜色的混合会导致永久性的变化,这种变化无法通过在背景色中再次绘制圆圈来消除。原因:颜色混合再次发生,但这只会导致效果变柔和。

简而言之,重绘只是覆盖了全覆盖的像素。边缘像素不完全是圆的一部分,因此无法掩盖边缘效果。

如果您需要删除圆圈,请考虑恢复原来的圆圈。大概可以复制原来的内容,然后画圆圈,然后当你想移动圆圈的时候,恢复原来的内容,重复这个过程。

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/

相关文章:

javascript - 有没有减少分数的JavaScript函数

javascript - 将函数拆分为更小的函数

silverlight - 与 Internet Explorer 兼容的多文件上传

javascript - WebGL 创建纹理

javascript - Angular 2发送授权 header

javascript - 使用 Jade 和 express 访问对象内的 json 对象

javascript - html5 Canvas : maxWidth argument to fillText produces ugly results in Chrome

javascript - 物体上的声音效果 p5.js

html - css:为什么我的背景图像在悬停时会跳跃?

html - 摆脱子菜单中的底部边框