HTML5画布调整大小时闪烁问题

4
我注意到在调整大小时动画画布控件出现了闪烁。
你可以在此页面上看到它的效果。拖动'width'滑块左右移动以自行尝试。我在运行Linux上的Chrome 26.0.1410.43中看到这种闪烁。目前,只有当Firefox支持HTML5的<input type="range">时,此页面才能正常工作。
我已经尝试在这个jsFiddle中缩小示例来重现此问题。它不是很明显,但对我来说会在画布宽度约为可用宽度的90%时发生。
代码在捕获requestAnimationFrame,并且调整大小会擦除画布。我希望在浏览器绘制帧之前会调用渲染回调。但事实并非如此,因为白色背景在调整大小期间偶尔显示出来。
是否有任何方法可以避免这种情况?
1个回答

5
当你设置canvas.width或canvas.height时,它会清除画布,再加上重绘,这就会导致你看到的闪烁。
你可以通过在调整大小之前将画布保存到临时画布中,然后在调整大小后重新绘制回来来减轻这种情况。
这是我的调整大小函数:
    function resize(width, height) {
        //Create temp canvas and context
        var tempContext = Utils.Canvas.Create2DContext(context.canvas.width, context.canvas.height);

        //Draw current canvas to temp canvas
        tempContext.drawImage(context.canvas, 0, 0);

        //Resize current canvas
        context.canvas.height = height;
        context.canvas.width = width;

        //Draw temp canvas back to the current canvas
        context.drawImage(tempContext.canvas, 0, 0);
    }

如果你将大小调整为较小的尺寸,则临时画布将被“覆盖”,因此它将完全填充当前画布。但是,如果您将大小调整为较大的尺寸,则您的临时画布仅会填充当前画布的一部分。未填充的部分仍将闪烁,因为它被重新绘制。
如果您想变得更加高级,可以尝试绘制正确(最终)大小的临时画布,而不仅仅是复制当前画布。这会更慢,但可能会消除所有闪烁。
在我的情况下,我正在调整大小以填充一个div,因此在底部和右侧边缘有一点闪烁是可以容忍的,肯定比整个闪烁要好得多。
编辑:
这是您的jsFiddle的更新,应用了我的更改:

jsfiddle.net/Uz5Pt/13

它似乎比我在应用程序中使用的地方效果更好!您几乎看不到任何新创建的画布位上的闪烁。


谢谢您的回答。我不确定这与我的做法有多大不同,因为我在调整大小后通过我的“draw”函数重新绘制整个内容。问题似乎是浏览器调整大小、清除、绘制,然后调用我的重绘,然后再次绘制。您尝试增加我的jsFiddle中的滑块了吗? - Drew Noakes
嗨,Drew,我已经自作主张地将我的修复应用到了你的jsFiddle上。http://jsfiddle.net/Uz5Pt/13/ 希望它能符合你的要求! - user310988
谢谢,看起来很不错。我会进一步查看,尝试理解为什么你的代码有效而我的代码无效。你能说一下吗?另外,如果将滑块拖到零,你的Fiddle就会崩溃 :) - Drew Noakes
我猜它会崩溃,因为它不喜欢制作0宽度的画布或类似的东西...但这需要更多的调试,超出了这个问题的范围;) - user310988

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接