javascript - 为什么更改选项卡时 Canvas 动画有时会失败?

标签 javascript html canvas html5-canvas

我创建了一个简单的 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>

问题是:

  • 导致该错误的原因
  • 如何修复它

编辑

  1. Udapte 问题,使用 @theusaf 的代码解决了一个仅在大时期内发生的问题。 (将时间段更改为 150)

最佳答案

发生这种情况的原因是 requestAnimationFrame 会暂停,直到用户返回选项卡,从而创建一个较大的间隔。这会将 red.xred.y 设置为非常大的数字。然后,盒子的速度不断交换,这意味着盒子停留在 Angular 落里。

例如:用户离开一段时间,抽奖后,red.xred.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/

相关文章:

java - 如何调用 javascript 函数并获取它返回的 html 代码,Java,Android

javascript - 如何通过点击从数组中获取不重复的随机字符串?

javascript - 如何在 Chart.js 中更改隐藏图例项目的颜色而不是删除线

javascript - NodeJS + Socket.IO : Problem accessing room variables

javascript - 如何将分数插入数组,然后显示

html - Bootstrap 工作室 : Adding border to elements

html - 使用 CSS 的锥形 div

Javascript - 使用宽度和高度的百分比在 Canvas 上绘制

javascript - 当事件发生时获取 HTML5 Canvas 图形 (Arc) 的尺寸

java - 如何使用 Vaadin 将图像上传到 Canvas ?