所以,我正在做一个动画(不在网站/网页上!),使用Javascript.对于动画,我使用requestAnimationFrame而不是setInterval,因为setInterval不能很好地满足我的需要.
然而,虽然requestAnimationFrame在功能强大的设备上运行良好,但是慢速设备无法跟上标准的60 FPS,从而减慢了整个动画时间.
有没有办法让动画在一个时间范围内工作,并且FPS会根据它的保持程度而有所不同?其他想法也是受欢迎的.
(注意,我真的不想发布代码,只是听听我的意见.我只是想要想法)
所以我用requestAnimationFrame编写了一个有效的应用程序(实际上是它的一半).在项目过于复杂之前,我急于以面向对象的方式重写它,这样我们就可以更好地实现插件(并且还可以在不更改整个应用程序的情况下修复模块).事实上,该应用程序的第一个版本实际上已经搞砸了,并且由很多测试代码组成.
所以我有以下内容:
Aventura.prototype.update = function() {
var av = this;
requestAnimationFrame(av.update);
/* ... frame code ... */
};
Run Code Online (Sandbox Code Playgroud)
我在控制台日志中得到"Uncaught TypeError:Type error",就在requestAnimationFrame行中.我知道我的浏览器有一个正确的requestAnimationFrame实现,因为我完全使用了我的应用程序的混乱版本.
我得出的结论是它引发了一个异常,因为我正在调用一个方法,它是调用者自己的父对象的一个成员(我知道它的方法完全相同,但问题显然不是自调用,因为那是皇家空军应该做什么).什么是错的线索?
我试图取消一个requestAnimationFrame循环,但我不能这样做,因为每次requestAnimationFrame调用时,都会返回一个新的计时器 ID,但我只能访问第一次调用的返回值requestAnimationFrame。
具体来说,我的代码是这样的,我认为这并不完全不常见:
function animate(elem) {
var step = function (timestamp) {
//Do some stuff here.
if (progressedTime < totalTime) {
return requestAnimationFrame(step); //This return value seems useless.
}
};
return requestAnimationFrame(step);
}
//Elsewhere in the code, not in the global namespace.
var timerId = animate(elem);
//A second or two later, before the animation is over.
cancelAnimationFrame(timerId); //Doesn't work!
Run Code Online (Sandbox Code Playgroud)
因为所有后续调用都requestAnimationFrame在该函数内step,所以在我想要调用的事件中,我无权访问返回的计时器 ID cancelAnimationFrame。
看看Mozilla(显然还有其他人这样做)的方式,看起来他们在代码中声明了一个全局变量(myReq在 Mozilla 代码中),然后将每次调用的返回值分配给 …
javascript global-variables requestanimationframe cancelanimationframe
我使用Three.js加载了 navMesh 和 Animal 。动物在地图上移动。但是,当我更改选项卡动物移动暂停,如果再次打开该选项卡动物从暂停点再次移动。如何播放选项卡更改或选项卡背景的继续动画。
function animate() {
var currTime = window.performance.now();
var delta = (currTime - lastFrameTime) / 1000;
var dTime = Math.min(delta, maxFrameTime);
elapsedTime += delta;
lastFrameTime = currTime;
tick(dTime);
requestAnimationFrame( animate );
render();
}
Run Code Online (Sandbox Code Playgroud) 我认为传递的时间戳参数requestAnimationFrame计算错误(在 Chrome 和 Firefox 中测试)。
在下面的代码片段中,我有一个循环,大约需要。300ms(您可能需要调整循环迭代的次数)。计算出的值delta应始终大于打印的循环“持续时间”。奇怪的是,有时慢有时不慢。为什么?
let timeElapsed = 0;
let animationID;
const loop = timestamp => {
const delta = timestamp - timeElapsed;
timeElapsed = timestamp;
console.log('delta', delta);
// some heavy load for the frame
const start = performance.now();
let sum = 0;
for (let i = 0; i < 10000000; i++) {
sum += i ** i;
}
console.warn('duration', performance.now() - start);
animationID = requestAnimationFrame(loop)
}
animationID = requestAnimationFrame(loop);
setTimeout(() => {
cancelAnimationFrame(animationID);
}, …Run Code Online (Sandbox Code Playgroud) 我有最简单直接的画布动画:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.canvas.width = 700;
ctx.canvas.height = 300;
var x = 0;
var update = function() {
x = x + 6;
}
var draw = function() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(x, 10, 30, 30);
}
let lastRenderTime = 0
const frameRate = 60;
function main(currentTime) {
window.requestAnimationFrame(main)
const secondsSinceLastRender = (currentTime - lastRenderTime) / 1000
if (secondsSinceLastRender < 1 / frameRate) return
lastRenderTime = currentTime
update()
draw()
}
window.requestAnimationFrame(main)Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas"></canvas> …Run Code Online (Sandbox Code Playgroud)我有以下功能,通过每次“勾选”调整元素的样式,将某些元素“向上”滚动到视图之外:
const incr = 1;
let moved = 0;
function changeHeight( children, duration, setTop) {
// duration = 1500
const height = children.clientHeight; // in this case, 166px
let moved = 0;
const slideUp = function (timestamp) {
// we're done if the amount moved is larger than height
if ( moved < height ) {
children.style.top = `${ setTop( moved, height ) }px`;
moved = moved + incr // move by some amount
requestAnimationFrame(slideUp)
} else {
// reset …Run Code Online (Sandbox Code Playgroud) 今天我在接受采访时被问到这个问题。我无法回答这个问题,面试官说有一个特殊的队列用于 requestAnimationFrame 回调。但我找不到任何这方面的信息。
如果 rAF 有它自己的队列,那么为什么这个队列从未在任何地方被提及?当我们谈论事件循环时,我们只提到宏任务队列和微任务队列?
我编写的游戏的性能一直存在很大的问题。出于某种原因,游戏时口吃,似乎要么绘制同一帧两次,要么跳过该帧的绘制。正如您在图像中看到的那样,由于某种原因,当发生这种“抽动/停顿”时,FPS下降到30,帧时间是原来的两倍。这些口吃非常频繁,每1-5秒发生一次。我已经测试了内存泄漏,没有异常,测试了垃圾回收,没有异常。在update()函数中使用requestAnimationFrame调用它们。这是一个jsfiddle我放在一起。只需右键单击输出,转到时间轴和配置文件20秒钟。您会看到FPS随机下降到30。在小提琴上,大多数代码来自我添加的外部文件,因此对该问题并不重要。我在579行添加了一行,以显示重要代码的起始位置。导致此问题的两个函数是moveAllGameRectangles();。renderTheGameObjects(); 在线上,小提琴上是1180和1098。如果您可以看一下这两个功能,并告诉我是否看到可以改善性能的任何东西,那就太好了。我出于测试目的删除了碰撞检测。我几个月来一直遇到这个问题,所以任何帮助都将非常巨大!
(function() {
var c = document.querySelector("canvas");
var ds = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
var theMaxWidth = c.width / 4.5;
if (c.height === 1743 || c.height === 1744 || c.height === 1740) {
var gameVelocity = 60;
} else {
var gameVelocity = 70;
}
var so = Math.round(c.height / gameVelocity + 65);
var halfVelocity = gameVelocity * 4;
var halfVelocityModulus = gameVelocity * 2;
var modulusNumber = 17;
var OPENING = 0
var …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用window.requestAnimationFrame()时跟踪时间,但即使我要增加的值不是NaN,+ =运算符也会继续返回NaN
var elapsedTime = 0
var lastTime = 0
var between = 500
var count = 0
var betweenCount = 0
function frame(time) {
elapsedTime = time - lastTime
console.log(elapsedTime)
lastTime = time
betweenCount += elapsedTime
console.log(betweenCount)
window.requestAnimationFrame(frame)
}
frame()
Run Code Online (Sandbox Code Playgroud)
betweenCount应该跟踪自上次重置以来的总经过时间,但是一旦为其指定了lapsedTime,它就变为NaN,但是此时的经过时间不是NaN。