javascript - HTML5 Canvas : Elements drawn with/cached for drawImage are smoothed when scaled and/or moved

标签 javascript html canvas

我确实知道 drawImagexy 的浮点/整数值的情况。但我需要的是能够缓存我的形状的流畅动画。

例如,我想在 Canvas 上绘制一些复杂的形状(即 SVG-tiger,converted to canvas-commands)一次,然后使用 ctx.translate平滑 移动它和 ctx.drawImage。然后我需要浮点值,因为我得到了一步一步的移动:

这是 JSFiddle 上的示例:

  • One : 速度快,Math.floor 应用于translate 参数(xy 等于以秒为单位的时间乘以 10):动画很奇怪(连续的,不流畅)。
  • Two : 速度较慢,Math.floor 应用于translate 参数(xy 等于以秒为单位的时间): 动画很奇怪(连续的,不流畅)。
  • Three :速度快,无舍入,浮点值(xy 等于以秒为单位的时间乘以 10)。速度快,所以动画看起来不错。
  • Four :速度较慢,没有舍入,浮点值(xy 等于以秒为单位的时间)。速度很慢,因此动画看起来脉动为什么?

最后一个案例让我很困惑。我的尝试有错吗?有可能让这个缓存技巧发挥作用吗?

在 Firefox 中,有一个名为 mozImageSmoothingEnabled 的 Canvas 属性(see),但在其他浏览器中没有任何帮助。它还消除了路径平滑。

代码摘录:

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) {
    . . .
}

最佳答案

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

只是澄清一下:

shapeCanvas.style.width = w + 'px';
shapeCanvas.style.height = h + 'px';

真的不值得做。如果它只是一个内存中的 Canvas ,则设置样式毫无意义,而且无论如何您都不应该真的想设置 Canvas 的宽度和高度样式,这只会混淆事情。

ellisbben 在评论中所说的几乎就是正在发生的事情。

我敢打赌,可以通过一些骇人听闻的方式来解决这个问题。一种方法可能是确保它永远不会绘制在整数像素上。另一种可能是在绘制任何东西之前使用 ctx.scale(.99,.99) 以便它始终消除锯齿。很难在这里获得一致的解决方案,因为不同的浏览器对抗锯齿的实现是不同的。

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

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

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

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

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

我的实验都没有导致你的脉动结束,至少在微观层面上没有。如果您想将像素完美的图像动画化到半像素空间,我认为这就是您将不得不忍受的东西。

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

老实说,您最好不要缓存这些动画路径,直到您绝对需要它们的性能。缓存你制作的程式化按钮和其他静态东西,但是如果你有需要缓慢而精确地移动并且看起来非常漂亮的动画路径,你最好坚持我的缓存优化的真实东西,除非你真的 那些人也需要它。

关于javascript - HTML5 Canvas : Elements drawn with/cached for drawImage are smoothed when scaled and/or moved,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8412841/

相关文章:

javascript - 如何在缩放 Canvas 中获取像素范围?

javascript - Luhn 检查 Javascript

javascript - AngularJS [$注入(inject)器 :unpr] Unknown provider: dataProvider <- data <- PageCtrl

html - 标题图标、标题和导航栏在屏幕调整大小时溢出标题容器

javascript - 切换不显示容器

javascript - Google map - 多个标记 - 1 个 InfoWindow 问题

android - 如何在像 Wifi Analyzer App 这样的 Android 中绘制图表?

javascript - 在 Canvas 中旋转 Sprite

javascript - 没有马赛克的平铺 <div> 元素

javascript - 如何在 JQuery Flot 上复制 Y 轴