为什么 jQuery 不使用 requestAnimationFrame?

有些浏览器支持 requestAnimationFrame,那么为什么不使用它呢?毕竟,这是 支持自谷歌 Chrome 10。尽管如此,jQuery 似乎没有使用它。我已经找到了一个 漏洞报告关于它,但没有给出真正的解释?但我相信 jQuery 的人有他们的理由。

他们为什么不用这个很棒的 API 呢?

29098 次浏览

In the jQuery source for v1.6.2, I see requestAnimationFrame being used if it's present. I haven't studied the code in great detail to see that it's being used for everything it could be used for, but it is being used in the animation section of the code instead of a call to setInterval(). Here's the code from 1.6.2:

// Start an animation from one number to another
custom: function( from, to, unit ) {
var self = this,
fx = jQuery.fx,
raf;


this.startTime = fxNow || createFxNow();
this.start = from;
this.end = to;
this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
this.now = this.start;
this.pos = this.state = 0;


function t( gotoEnd ) {
return self.step(gotoEnd);
}


t.elem = this.elem;


if ( t() && jQuery.timers.push(t) && !timerId ) {
// Use requestAnimationFrame instead of setInterval if available
if ( requestAnimationFrame ) {
timerId = true;
raf = function() {
// When timerId gets set to null at any point, this stops
if ( timerId ) {
requestAnimationFrame( raf );
fx.tick();
}
};
requestAnimationFrame( raf );
} else {
timerId = setInterval( fx.tick, fx.interval );
}
}
},

I am not yet using 1.6.4 so I don't know about that version. If it's not in that version, then there must have been some issues so it was removed.

EDIT:

If you read this blog post, it sounds like it was pulled out of 1.6.3 and perhaps will be put back in 1.7 and the main reason it was pulled is because it broke some things people were "incorrectly" using the animation queue for (though perhaps that is a matter of opinion).

In ticket #9381 you can read why they stopped using requestionAnimationFrame after some time.

To summarize, problems were that animations didn't run (browsers try to reduce CPU load) when window didn't have focus, which is OK if the window is hidden, but not if it is visible, just out of the focus. Furthermore, animation queues piled up and after window regained focus, things went berserk. This would require ugly changes in the code and/or changes how people add things to the animation queue. So it was decided that support is removed until there is some better way to do this.

Given the other answers and objections here I wanted to test this out on a simple slideshow animation:

http://brass9.com/nature

As of 2013 the objections in other answers here no longer appear to be significant. I've added

https://github.com/gnarf/jquery-requestAnimationFrame/blob/master/src/jquery.requestAnimationFrame.js

to my existing animation code, and verified it's switching on and affecting the fade animations in use. It works reliably, even in background windows, in Chrome 30, IE 11, and FF 24. Testing Android 2.3, it appears to use the polyfill and work as expected.

jQuery 3

jQuery 3.0 integrates requestAnimationFrame. Basically, jQuery could handle it fine, but some users would call .setInterval(function() { tag.animate(, screwing it up. Thus the punt to major version release. jQuery 3 does not and will never support IE8 and below, so if you have IE8 users, stick with jQuery 1.x.

CSS Transitions

In my testing, the CPU/battery-saving claims of requestAnimationFrame are false promises. I see high CPU usage with it on, for example, long-fades. What does save CPU/battery is CSS Transitions, probably because the browser, especially mobile browsers, get to make much stronger assumptions about what you intend and what else is being asked of them, and native code is still faster than Javascript+DOM.

So if you really want to save CPU/battery, CSS Transitions are for you. IE9 and below can't handle them and there are still plenty of users out there, so consider jquery.transit and their Fallback to animate at the bottom of the page.