我创建了一个简单的 JavaScript Canvas 动画,我注意到当我更改到另一个选项卡然后返回到原始选项卡时,有时该框会保持移动并粘在一个边框上或在一个 Angular 落保持安静。它发生在小时间段和大时间段内。
我已经在 Chrome 和 Firefox 最新版本中对其进行了测试,但我不知道是什么导致了该错误。
这是jsfiddle中的代码:link
这是一个代码片段:
var canvas = document.getElementById('animation');
var ctx = canvas.getContext('2d');
var startTime;
var elapsed;
var oldTimeStamp;
var interval;
function createBox(x, y, width, height, vx, vy, color) {
this.x = x
this.y = y
this.width = width
this.height = height
this.vx = vx
this.vy = vy
this.color = color
this.draw = function () {
ctx.fillStyle = this.color
ctx.fillRect(
Math.max(Math.min(this.x, canvas.width-this.width), 0),
Math.max(Math.min(this.y, canvas.height-this.height), 0),
this.width,
this.height
);
}
}
var red = new createBox(0, 0, 50, 75, 0.1, 0.2, "gray")
function step(timeStamp) {
// Time
if (startTime === undefined) {
startTime = timeStamp
oldTimeStamp = timeStamp
}
elapsed = timeStamp - startTime;
interval = timeStamp - oldTimeStamp
if(interval > 150){
interval = 150
}
oldTimeStamp = timeStamp
// Draw
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (red.y + red.vy > canvas.height-red.height || red.y + red.vy < 0) {
red.vy = -red.vy;
}
if (red.x + red.vx > canvas.width-red.width || red.x + red.vx < 0) {
red.vx = -red.vx;
}
red.x = red.x + red.vx * interval
red.y = red.y + red.vy * interval
red.draw()
// Request new animation frame
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
canvas {
border: 1px solid black;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Canvas2-Bug</title>
</head>
<body>
<canvas id="animation" width="300" height="300"></canvas>
</body>
</html>
问题是:
- 导致该错误的原因
- 如何修复它
编辑
- Udapte 问题,使用 @theusaf 的代码解决了一个仅在大时期内发生的问题。 (将时间段更改为 150)
最佳答案
发生这种情况的原因是 requestAnimationFrame
会暂停,直到用户返回选项卡,从而创建一个较大的间隔
。这会将 red.x
和 red.y
设置为非常大的数字。然后,盒子的速度不断交换,这意味着盒子停留在 Angular 落里。
例如:用户离开一段时间,抽奖后,red.x
和red.y
是诸如500
的数字
red.x/red.y + red.vx/red.vy
将始终大于 canvas.height/width - red.height/width
red.vx/red.vy
然后每帧从负值交换到正值,然后再交换回负值。
要解决此问题,您可以添加一个条件以确保 interval
不会变得太高(超过 50):
var canvas = document.getElementById('animation');
var ctx = canvas.getContext('2d');
var startTime;
var elapsed;
var oldTimeStamp;
var interval;
function createBox(x, y, width, height, vx, vy, color) {
this.x = x
this.y = y
this.width = width
this.height = height
this.vx = vx
this.vy = vy
this.color = color
this.draw = function () {
ctx.fillStyle = this.color
ctx.fillRect(
Math.max(Math.min(this.x, canvas.width-this.width), 0),
Math.max(Math.min(this.y, canvas.height-this.height), 0),
this.width,
this.height
);
}
}
var red = new createBox(0, 0, 50, 75, 0.1, 0.2, "gray")
function step(timeStamp) {
// Time
if (startTime === undefined) {
startTime = timeStamp
oldTimeStamp = timeStamp
}
elapsed = timeStamp - startTime;
interval = timeStamp - oldTimeStamp;
if(interval > 50){interval=50}
oldTimeStamp = timeStamp
// Draw
ctx.fillStyle = 'rgba(255, 255, 255, 1)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (red.y + red.vy > canvas.height-red.height || red.y + red.vy < 0) {
red.vy = -red.vy;
}
if (red.x + red.vx > canvas.width-red.width || red.x + red.vx < 0) {
red.vx = -red.vx;
}
red.x = red.x + red.vx * interval
red.y = red.y + red.vy * interval
red.draw()
// Request new animation frame
window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
canvas {
border: 1px solid black;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Canvas2-Bug</title>
</head>
<body>
<canvas id="animation" width="300" height="300"></canvas>
</body>
</html>
关于javascript - 为什么更改选项卡时 Canvas 动画有时会失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63101717/