HTML5画布:在缩放和/或移动时,使用/ cached为drawImage绘制的元素将被平滑

sha*_*sir 6 javascript html5 canvas

我知道drawImage's xy.的浮点数/整数值的情况.但我需要的是一个平滑的动画,能够缓存我的形状.

例如,我想将一些复杂的形状(即SVG-tiger,转换为canvas-commands)绘制到canvas一次,然后使用和平滑移动它.我需要浮动值,因为相反,我得到了一步一步的移动:ctx.translatectx.drawImage

以下是JSFiddle的示例:

  • :快速,Math.floor应用于translate参数(x并且y等于以秒为单位的时间乘以10):动画很奇怪(顺序,不顺畅).
  • :慢速,Math.floor应用于translate参数(x并且y等于以秒为单位的时间):动画很奇怪(顺序,不顺畅).
  • :速度快,没有舍入,浮点值(xy以秒乘以等于时间10).速度很快,所以动画效果很好.
  • :慢的速度,没有舍入,浮点值(xy以秒等于时间).速度很慢,因此动画看起来很动人.为什么?

最后一个案例让我感到困惑.我的尝试错了,有可能让这个缓存技巧很好吗?

在Firefox中,有一个名为canvas的属性mozImageSmoothingEnabled(请参阅参考资料),但在其他浏览器中没有任何帮助.它还删除了平滑路径.

代码提取:

var shapeCanvas = null;
var w = 320, h = 240;
var startTime = 0;

function start() {
    startTime = Date.now();
    var docCanvas = document.getElementById('canvas');
    . . .
    shapeCanvas = document.createElement('canvas');
    . . .
    drawShape(shapeCanvas.getContext('2d'));

    drawNext(docCanvas.getContext('2d'));
}

function drawNext(ctx) {
    var msec = (Date.now() - startTime);
    var time = msec / 1000; // seconds passed from start
    ctx.clearRect(0, 0, w, h);

    ctx.save();
    // the lines to change: time | (time * 10) | Math.floor(time * 10)
    ctx.translate((time < 500) ? Math.floor(time * 10) : 500,
                  (time < 500) ? Math.floor(time * 10) : 500);
    ctx.drawImage(shapeCanvas, 0, 0);
    ctx.restore();

    __nextFrame(function() {
       drawNext(ctx);
    });
}

function drawShape(ctx) {
    . . .
}
Run Code Online (Sandbox Code Playgroud)

Sim*_*ris 4

我在你的第一个链接中写了教程。

只是为了消除误会:

shapeCanvas.style.width = w + 'px';
shapeCanvas.style.height = h + 'px';
Run Code Online (Sandbox Code Playgroud)

真的不值得做。如果它只是一个内存中的画布,那么设置样式是没有意义的,并且无论如何你都不应该真正想要设置画布的宽度和高度样式,它只会让事情变得混乱。

埃利斯本在评论中所说的几乎就是正在发生的事情。

我敢打赌,可以通过一些黑客的方式来绕过它。一种方法可能是确保它永远不会绘制在整数像素上。另一种可能是在绘制任何内容之前使用ctx.scale(.99,.99),因此它始终是抗锯齿的。在这里很难得到一致的解决方案,因为不同的浏览器的抗锯齿实现是不同的。

以下是我自己的一些实验:

http://jsfiddle.net/KYZYT/29/

前两个是从画布绘制的形状,也是从 PNG 绘制的形状

后两个是同一对,但按比例缩放.99,.99

最后一张是真人真事。它仍然有点模糊,但看起来比使用图像清晰得多。

我的所有实验都不会导致你的脉动结束,至少在微观层面上是这样。我认为如果您想将像素完美的图像动画到半像素空间上,这就是您必须忍受的事情。

如果你真的觉得你不能只在完美的像素上绘制,那么你的(第二)最好的一致性选择可能是找到一种方法来始终强制消除锯齿。确保始终将其转换为非整数或稍微缩放它是不错的选择,但可能还有其他选择。

老实说,最好的办法是不要缓存这些动画路径,除非您绝对需要它们的性能。缓存您制作的风格化按钮和其他静态内容,但是如果您有需要缓慢而精确地移动并且看起来非常好的动画路径,那么您最好坚持使用真实的内容而不是我的缓存优化,除非您确实需要它那些也是。