【问题标题】:Why when changing tabs sometimes canvas animation fails?为什么在更改选项卡时有时画布动画会失败?
【发布时间】:2020-07-26 23:49:21
【问题描述】:

我创建了一个简单的 JavaScript 画布动画,并且我注意到当我切换到另一个选项卡然后返回到原来的选项卡时,有时框会在一个边框上保持移动或在一个角落保持安静。它发生在大大小小的时间段内。

我已在 Chrome 和 Firefox 最新版本中对其进行了测试,但我不知道是什么导致了该错误。

这是 jsfiddle 中的代码:link

这是一个代码 sn-p:

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. 使用来自@theusaf 的代码的Udapte 问题解决了一个仅在大时间段内发生的问题。 (将时间段更改为 150)

【问题讨论】:

  • 有趣的问题,我可以确认这是一个问题
  • @BobvanLuijt 我认为这也是一个奇怪的问题。

标签: javascript html canvas html5-canvas


【解决方案1】:

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

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

【讨论】:

  • 谢谢,这是一个问题,但另一个问题仍然会在较小的时间段内发生,我会用您的代码修改问题。
猜你喜欢
  • 2018-07-31
  • 2018-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-28
  • 2013-03-06
  • 1970-01-01
相关资源
最近更新 更多