据我所知,JS requestAnimationFrameAPI的使用是针对帧率不需要控制的情况,但我有一个用例,<canvas>只有在某个fps间隔内的更新才可能在1之间的任何地方.和25(每秒 1到25 帧之间).那么我可以以某种方式仍然有效地使用rAF来实现它提供的优化吗?
这个问题与我的问题有相似之处,但在那个问题的背景下,我接受的答案对我来说几乎没有任何意义.
我有两个可能的解决方案.第一个涉及使用while循环在requestAnimationFrame从回调内调用之前停止脚本执行指定的延迟.在我看到这个的例子中,它有效地限制了动画的fps,但它似乎也减慢了整个标签的速度.这仍然是一个很好的解决方案吗?第二个替代方案,如我在上面提到的问题中所提到的,requestAnimationFrame在一个内部调用setInterval.对我来说似乎有点费解,但它可能是最好的选择吗?
或者有更好的替代方法来实现这一目标吗?
fre*_*und 14
Yoshi的答案可能是解决这个问题的最佳代码.但我仍然认为这个答案是正确的,因为经过一些研究后我基本上发现我的问题无效.requestAnimationFrame实际上是为了保持帧速率尽可能高,并且它优化了动画要保持一致和平滑的场景.
值得注意的是,你不需要requestAnimationFrame进行优化(尽管rAF被吹捧为一个出色的性能助推器),因为浏览器仍然可以优化常规绘图<canvas>.例如,当标签没有聚焦时,Chrome for one会停止绘制其画布.
所以我的结论是这个问题无效.希望这有助于任何想要与我相似的人.
这只是一个概念证明.
我们所做的只是设置每秒帧数和每帧之间的间隔.在绘图功能中,我们从当前时间中扣除最后一帧的执行时间,以检查自最后一帧起经过的时间是否超过我们的间隔(基于fps).如果条件的计算结果为true,我们将设置当前帧的时间,该时间将是下一个绘图调用中的"最后一帧执行时间".
var Timer = function(callback, fps){
var now = 0;
var delta = 0;
var then = Date.now();
var frames = 0;
var oldtime = 0;
fps = 1000 / (this.fps || fps || 60);
return requestAnimationFrame(function loop(time){
requestAnimationFrame(loop);
now = Date.now();
delta = now - then;
if (delta > fps) {
// Update time stuffs
then = now - (delta % fps);
// Calculate the frames per second.
frames = 1000 / (time - oldtime)
oldtime = time;
// Call the callback-function and pass
// our current frame into it.
callback(frames);
}
});
};
Run Code Online (Sandbox Code Playgroud)
用法:
var set;
document.onclick = function(){
set = true;
};
Timer(function(fps){
if(set) this.fps = 30;
console.log(fps);
}, 5);
Run Code Online (Sandbox Code Playgroud)
http://jsfiddle.net/ARTsinn/rPAeN/
你可以做什么,虽然我真的不知道这是否真的更好是:
requestAnimationFramesetInterval使用固定的fps 更新可见上下文例:
<canvas id="canvas"></canvas>?
<script type="text/javascript">
(function () {
var
ctxVisible = document.getElementById('canvas').getContext('2d'),
ctxHidden = document.createElement('canvas').getContext('2d');
// quick anim sample
(function () {
var x = 0, y = 75;
(function animLoop() {
// too lazy to use a polyfill here
webkitRequestAnimationFrame(animLoop);
ctxHidden.clearRect(0, 0, 300, 150);
ctxHidden.fillStyle = 'black';
ctxHidden.fillRect(x - 1, y - 1, 3, 3);
x += 1;
if (x > 300) {
x = 0;
}
}());
}());
// copy the hidden ctx to the visible ctx on a fixed interval (25 fps)
setInterval(function () {
ctxVisible.putImageData(ctxHidden.getImageData(0, 0, ctxHidden.canvas.width, ctxHidden.canvas.height), 0, 0);
}, 1000/40);
}());
</script>
Run Code Online (Sandbox Code Playgroud)