Javascript 如何使用 requestAnimationFrame?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5605588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to use requestAnimationFrame?
提问by einstein
I'm new to animation, but I have recently created an animation using setTimeout
. The FPS was too low, so I found a solution to use requestAnimationFrame
, described in this link.
我是动画新手,但我最近使用setTimeout
. FPS 太低,所以我找到了一个解决方案requestAnimationFrame
,在这个链接中描述。
So far, my code is:
到目前为止,我的代码是:
//shim layer with setTimeout fallback
window.requestAnimFrame = (function(){
return
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback){
window.setTimeout(callback, 1000 / 60);
};
})();
(function animloop(){
//Get metrics
var leftCurveEndX = finalLeft - initialLeft;
var leftCurveEndY = finalTop + finalHeight - initialTop;
var rightCurveEndX = finalLeft + finalWidth - initialLeft - initialWidth;
var rightCurveEndY = leftCurveEndY;
chopElement(0, 0, 0, 0, leftCurveEndX, leftCurveEndY, rightCurveEndX, rightCurveEndY);//Creates a new frame
requestAnimFrame(animloop);
})();
This stops during the first frame. I have a callback function requestAnimFrame(animloop);
in the chopElement
function.
这在第一帧期间停止。我在函数requestAnimFrame(animloop);
中有一个回调chopElement
函数。
Also, is there a more thorough guide to using this API?
另外,是否有更全面的使用此 API 的指南?
回答by Jan
Warning! This question is not about the best way to shimrequestAnimFrame
. If you are looking for that, move on to any other answer on this page.
警告!这个问题不是关于填充的最佳方法requestAnimFrame
。如果您正在寻找那个,请转到此页面上的任何其他答案。
You got tricked by automatic semicolon insertion. Try this:
你被自动分号插入欺骗了。尝试这个:
window.requestAnimFrame = function(){
return (
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback){
window.setTimeout(callback, 1000 / 60);
}
);
}();
javascript automatically puts a semicolon behind your return
statement. It does this because it is followed by a newline and the next line is a valid expression. In fact it gets translated to:
javascript 会自动在您的return
语句后面放一个分号。这样做是因为它后跟一个换行符,下一行是一个有效的表达式。事实上,它被翻译成:
return;
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(/* function */ callback){
window.setTimeout(callback, 1000 / 60);
};
This code returns undefined
and never executes the code behind the return statement. So window.requestAnimFrame
is undefined
. When you call it in animloop
, the javascript produces an error and stops execution. You can solve the problem by enclosing the expression in parentheses.
此代码返回undefined
并且从不执行 return 语句后面的代码。所以window.requestAnimFrame
是undefined
。当您在 中调用它时animloop
,javascript 会产生错误并停止执行。您可以通过将表达式括在括号中来解决该问题。
May I recommend the Chrome developer tools or firebug to inspect javascript execution. With these tools you would have seen the error. You should go about debugging it as follows (I'm assuming Chrome):
我可以推荐 Chrome 开发人员工具或 firebug 来检查 javascript 执行。使用这些工具,您会看到错误。您应该按如下方式调试它(我假设是 Chrome):
- Execute the code (it produces unexpected results)
- Open the developer tools (right click -> Inspect Element) You will see a red x in the status bar at the right (this means there is an error in the execution)
- Open the console tab
- You will see
Uncaught TypeError: Property 'requestAnimFrame' of object [object DOMWindow] is not a function
- Type in the console:
window.requestAnimFrame
and press enter, you will see it isundefined
. By now you know that the problem is in fact unrelated torequestAnimationFrame
and that you should concentrate on the first part of your code. - Now it is a matter of narrowing down the code up to the point where it returns something. This is the difficult part and if you still don't find it at this point you might want to turn to the internet for more help.
- 执行代码(它会产生意想不到的结果)
- 打开开发者工具(右键-> Inspect Element)你会在右边的状态栏中看到一个红色的x(这意味着执行中有错误)
- 打开控制台选项卡
- 你会看见
未捕获的类型错误:对象 [object DOMWindow] 的属性“requestAnimFrame”不是函数
- 在控制台
window.requestAnimFrame
输入:然后回车,你会看到它是undefined
。现在您知道问题实际上与此无关requestAnimationFrame
,您应该专注于代码的第一部分。 - 现在的问题是将代码缩小到返回某些内容的程度。这是困难的部分,如果此时您仍未找到它,您可能需要求助于互联网以获得更多帮助。
Also, watch this videofor some good practices in writing javascript, He also mentions the evil automatic semicolon insertion.
此外,观看此视频以了解编写 javascript 的一些良好做法,他还提到了邪恶的自动分号插入。
回答by Gokhan Tank
/*
Provides requestAnimationFrame in a cross browser way.
http://paulirish.com/2011/requestanimationframe-for-smart-animating/
*/
if (!window.requestAnimationFrame) {
window.requestAnimationFrame = (function() {
return window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame || // comment out if FF4 is slow (it caps framerate at ~30fps: https://bugzilla.mozilla.org/show_bug.cgi?id=630127)
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
window.setTimeout(callback, 1000 / 60);
};
})();
}
animate();
function animate() {
requestAnimationFrame(animate);
draw();
}
function draw() {
// Put your code here
}
Have a look at the below jsfiddle example; It illustrates clearly what I mean;
看看下面的 jsfiddle 示例;它清楚地说明了我的意思;
http://jsfiddle.net/XQpzU/4358/light/
http://jsfiddle.net/XQpzU/4358/light/
Hope this helps!
希望这可以帮助!
回答by vsync
"Smart throttling so the event won't get fired more times than the screen can repaint the change:
“智能节流,因此事件不会被触发超过屏幕可以重新绘制更改的次数:
var requestFrame = window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
// polyfill - throttle fall-back for unsupported browsers
(function() {
var throttle = false,
FPS = 1000 / 60; // 60fps (in ms)
return function(CB) {
if( throttle ) return;
throttle = true;
setTimeout(function(){ throttle = false }, FPS);
CB(); // do your thing
}
})();
/////////////////////////////
// use case:
function doSomething() {
console.log('fired');
}
window.onscroll = function() {
requestFrame(doSomething);
};
html, body{ height:300%; }
body::before{ content:'scroll here'; position:fixed; font:2em Arial; }