使用JavaScript动画DIV会在Chrome上呈现工件

时间:2012-08-12 19:04:47

标签: javascript google-chrome animation

作为一个实验,我试图在不使用canvas对象的情况下在JavaScript中复制AS3的Sprite功能。我认为使用绝对定位的div并操纵他们的css属性将毫无疑问,但是在Chrome中动画会引入奇怪的文物(似乎是因为重绘问题)。

我找不到我做错了什么?事实上,代码非常简单。以下是我尝试的一些没有帮助的要点:

  • 使用相对定位的div(而不是绝对定位的。)
  • 使用边距(与顶部和左侧属性相对)。
  • 将对象直接附加到正文(而不是附加到容器div。)
  • 使用setTimeout(而不是requestAnimationFrame)

您可以在此处看到简化的小提琴:http://jsfiddle.net/BVJYJ/2/

编辑:http://jsfiddle.net/BVJYJ/4/

在这里,您可以在我的浏览器上看到工件:

The artifacts in Chrome

这可能是我的设置中的错误(Windows 7 64位,Chrome 21.0.1180.75)。没有其他浏览器出现此行为。如果有人可以评论我可能做错了什么,我将不胜感激。我对这背后的原因更加好奇,而不是一个解决方法。也就是说,欢迎每一个解释。 :)

编辑:示例代码中有一个错误导致使用setTimeout,即使我的印象是使用了RAF。 requestAnimationFrame解决了基本转换的问题,但问题仍然存在于CSS转换中,例如旋转。

The artifacts in Chrome with rotation transformation.

3 个答案:

答案 0 :(得分:28)

我的liteAccordion插件遇到了同样的问题。可以通过将背面可见性设置为隐藏在您正在设置动画的元素上来修复,如下所示:http://jsfiddle.net/ZPQBp/1/

答案 1 :(得分:3)

一些研究表明setTimeout可能由于各种原因而导致问题。你真的应该使用requestAnimationFrame

  

定时器不精确到毫秒。这是一些常见的计时器   分辨率1

     
      
  • Internet Explorer 8及更早版本的计时器分辨率为15.625ms
  •   
  • Internet Explorer 9及更高版本的计时器分辨率为4毫秒。火狐
  •   
  • 和Safari的定时器分辨率约为10毫秒。
  •   
  • Chrome的计时器分辨率为4毫秒。
  •   
     

版本9之前的Internet Explorer的计时器分辨率为15.625   ms 1,因此0到15之间的任何值都可以是0或15但是   没有其他的。 Internet Explorer 9将计时器分辨率提高到4毫秒,   但在动画方面,这仍然不是很具体。

     

Chrome的计时器分辨率为4毫秒,而Firefox和Safari则为10毫秒。   因此,即使您设置了最佳显示的间隔,您仍然是   只接近你想要的时间。

参考:http://www.nczonline.net/blog/2011/05/03/better-javascript-animations-with-requestanimationframe/

另外

  

setTimeout没有考虑到其中发生了什么   浏览器。页面可能隐藏在选项卡后面,占用CPU时   它不需要,或动画本身可以滚动   关闭页面使更新调用再次成为不必要的。 Chrome确实如此   在隐藏的选项卡中将setInterval和setTimeout限制为1fps,但这样   并不是所有浏览器都可以依赖。

     

其次,setTimeout仅在需要时更新屏幕,而不是   当计算机能够。这意味着你糟糕的浏览器必须   juggle重绘动画,同时重绘整个屏幕,和   如果您的动画帧速率与重绘不同步   你的屏幕,它可能会占用更多的处理能力。这意味着   更高的CPU使用率和你的计算机的风扇踢,或耗尽   移动设备上的电池。 Nicolas Zakas表现出色   解释影响计时器分辨率对相关动画的影响   article

参考:http://creativejs.com/resources/requestanimationframe/

答案 2 :(得分:1)

它与subpixel positioning有关。如果四舍五入到最近的像素,则不会看到这些渲染错误:

thisRef.block.style.left = Math.round((x + (mouseX - ox - x) * .125)) + "px";
thisRef.block.style.top = Math.round((y + (mouseY - oy - y) * .125)) + "px";