Firefox 中的 requestAnimationFrame 闪烁问题

Posted

技术标签:

【中文标题】Firefox 中的 requestAnimationFrame 闪烁问题【英文标题】:requestAnimationFrame flickering issue in Firefox 【发布时间】:2013-01-18 14:49:56 【问题描述】:

我正在尝试在画布上沿对角线方向制作一个圆圈。我正在使用 requestanimationframe。它在所有浏览器中都能顺利运行,但在 Firefox 中却不行。动画进行时会不断闪烁。请有人告诉我我做错了什么。我需要在 Firefox 中以至少合理的速度平滑动画。

这是我的简单代码,也许有人可以指出我在这里缺少什么..:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<style>
/*html  background: #000; */
</style>

<title>Test</title>
</head>

<body>
<script type="text/javascript">

    window.requestAnimFrame = (function()
      return  window.requestAnimationFrame       || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     || 
              function(/* function */ callback, /* DOMElement */ element)
                window.setTimeout(callback, 1000 / 60);
              ;
    )();

window.cancelRequestAnimFrame = ( function() 
    return window.cancelAnimationFrame          ||
        window.webkitCancelRequestAnimationFrame    ||
        window.mozCancelRequestAnimationFrame       ||
        window.oCancelRequestAnimationFrame     ||
        window.msCancelRequestAnimationFrame        ||
        clearTimeout
 )();  

var canvas, context, toggle;
var ctr = 0;
var request;

var x = 10;
var y = 10;


init();
animate();

function init() 

    canvas = document.createElement( 'canvas' );
    canvas.width = 512;
    canvas.height = 512;

    context = canvas.getContext( '2d' );

    document.body.appendChild( canvas );



function animate() 


    request = requestAnimFrame( animate );
    draw();



function draw() 

  context.clearRect(0,0,canvas.width,canvas.height);
  y+=2;
  x+=2;

  context.beginPath();
  context.arc(x, y, 3, 0, 2 * Math.PI, false);
  context.fillStyle = 'green';
  context.fill();
  context.lineWidth = 5;
  context.strokeStyle = '#003300';
  context.stroke();

    //cancelRequestAnimFrame(request); 



</script>

</body>
</html>

【问题讨论】:

我期待一个非常快速的回答这个问题,因为场景非常简单。在Firefox中不可能有流畅的html5画布动画吗?为什么在Firefox中完成它如此困难,我想知道! 我在 Mac 上的 Firefox 18 中没有看到这种闪烁。您使用的是哪个版本的 Firefox? 我刚刚在 windows pc 上的 Firefox 18 中尝试过。它不光滑。它在 chrome 中完美运行,但在 Firefox 中我可以看到它并不流畅。也许这是 Firefox 能做的最好的事情。我的客户使用 Firefox,所以我必须对这个问题做点什么!在这个例子中,我放置了一个简单的圆圈在画布上移动的场景。我的实际项目在每个循环迭代中都包含图像背景和非课程 javascript 逻辑。在 chrome、IE 和 safari 中都运行良好。任何想法! 【参考方案1】:

您的代码中有两处需要修改:

首先尝试新的requestAnimationFrame polyfill。

(function() 
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) 
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelRequestAnimationFrame = window[vendors[x]+
          'CancelRequestAnimationFrame'];
    

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) 
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function()  callback(currTime + timeToCall); , 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        ;

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) 
            clearTimeout(id);
        ;
())

如需深入解释,请阅读这篇文章:http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating

是你需要计算一个时间戳和下一个时间戳之间的增量。您正在使用一个固定值,每次渲染迭代都会增加一个。因为您的浏览器跟不上它可能会跳过一两帧的速度。这样你就可以顺利度过。

这是计算增量时间的方式:

end = Date.now();
delta = ( end - start ) / 1000.0 * 60;
end = start;

http://jsfiddle.net/p5c6c/1/

【讨论】:

感谢您的帖子。好吧,我已经尝试过这个 polyfill,但动画仍然不流畅。我不知道你提到的增量时间。我看到你在我的代码中添加了 delta 因子..但不幸的是它仍然在我的 firefox.damn firefox 上闪烁。 (您是否使用此代码获得流畅的动画?如果是,哪个 FF 版本!)我也读过这篇文章,但我无法了解在 Firefox 中拥有流畅(如在其他浏览器中)动画的秘密。我已经尝试了好几个星期了。我现在完全被火狐困住了。 FF 18.0.1。起初加载并不像它应该的那样平滑(可能是因为文档没有完全呈现),但在很长一段时间内,与我跳过帧的方法相比,它肯定会变得更平滑。 window.onload = function() i 厚应该可以解决问题。 好吧,我的问题仍然存在。我客户的 Firefox 也有同样的问题。它并不完全顺利。我对平滑度的定义是这个动画在 chrome 中的表现。 那跟代码没关系...反正尽量用增量时间代替定值... 是的,那段代码不会有任何问题。它只是FF处理动画的糟糕程度。我将尝试在其他地方找到解决我独特问题的方法。无论如何感谢您的帮助:)

以上是关于Firefox 中的 requestAnimationFrame 闪烁问题的主要内容,如果未能解决你的问题,请参考以下文章

css [隐藏滚动条]隐藏Firefox #firefox #css中的滚动条

Firefox中的可点击电话协议标签

Firefox中的iframe打印问题

Firefox 中的 requestAnimationFrame 闪烁问题

最新版本中的 Firefox 盒子阴影更轻

WebAPi - Firefox 和 chrome 中的 CORS