clearTimeout 不停止 canvas 动画

clearTimeout not stopping canvas animation

所以我有一个简单的 canvas 动画,我想使用拨动开关开始和停止。动画工作正常并启动,但 clearTimeout 似乎不起作用。

我确保变量 "timeOut" 是全局定义的,因此它应该可以访问它,这似乎是过去类似于此问题的常见建议。我在其他地方犯错了吗?在 Firefox、Chrome 和 Chromium 上试过。

let timeOut;

function circles() {
  let canvas = document.querySelector('canvas');
  canvas.width = document.querySelector('canvas').offsetWidth;
  canvas.height = document.querySelector('canvas').offsetHeight;
  let c = canvas.getContext('2d');
  let topRadius = 30;
  let colorArray = [
    '#ff0000',
    '#00ff00',
    '#0000ff',
  ]

  let mouse = {
    x: undefined,
    y: undefined
  }

  window.addEventListener('mousemove', function(e) {
    mouse.x = e.x;
    mouse.y = e.y;
  })

  window.addEventListener('resize', function() {
    canvas.width = document.querySelector('canvas').offsetWidth;
    canvas.height = document.querySelector('canvas').offsetHeight;
    init();
  });

  function Circle(x, y, dx, dy, radius) {
    this.x = x;
    this.y = y;
    this.dx = dx;
    this.dy = dx;
    this.radius = radius;
    this.minRadius = radius;
    this.color = colorArray[Math.floor(Math.random() * colorArray.length)];

    this.draw = function() {
      if (this.radius < 0) {
        this.radius = this.minRadius;
      }
      c.beginPath();
      c.arc(this.x, this.y, this.radius, 0, Math.PI*2, false);
      c.fillStyle = this.color;
      c.fill();
    }

    this.update = function() {
      if (this.y + this.radius > innerHeight || this.y - this.radius <= 0) {
        this.dy = -this.dy;
      }
      if (this.x + this.radius > canvas.width|| this.x - this.radius <= 0) {
        this.dx = -this.dx;
      }
      this.x+=this.dx;
      this.y+=this.dy;

      if (mouse.x - this.x < 50 && mouse.x - this.x > -50 && mouse.y - this.y < 50 && mouse.y - this.y > -50) {
        if (this.radius < topRadius) {
          this.radius += 1; 
        }
      } else if (this.radius > this.minRadius){
        this.radius -= 1;
      }

      this.draw();
    }
  }

  let circleArray = [];
  function init() {
    circleArray = [];
    for (let i =0; i<50; i++) {
      let radius = Math.random() * 10;
      let x = Math.random() * (canvas.width - radius*2) + radius;
      let y = Math.random() * (canvas.height - radius * 2) + radius;
      let dx = (Math.random() - 0.5) * 4;
      let dy = (Math.random() - 0.5 )* 4;
      circleArray.push(new Circle(x, y, dx, dy, radius));
    }
  }

  function animate() {
    requestAnimationFrame(animate);
    c.clearRect(0,0, canvas.width, innerHeight);

    for(let i=0; i < circleArray.length; i++) {
      circleArray[i].update();
    }
  }
  init();
  animate();
}

$('#startstop').click(function() {
  if(!timeOut) {
    timeOut = setTimeout(circles, 1000);
  } else {
    clearTimeout(timeOut);
    timeOut = null;
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div style="display: flex; justify-content: space-around;">
  <canvas style="width: 100px; height: 800px; background: red;"></canvas>

<div id="startstop">toggle</div>
</div>

此动画不会停止,因为您在 setTimeout 上调用了 clearTimeout,但它只运行一次。您的问题与 animate 函数有关。这相对循环requestAnimationFrame。您可以将其存储为请求,然后 cancelAnimationFrame

您非常接近解决方案 ;)

在函数 animate 中添加第 3 行(在 for 循环之前),即具有此值:

if (!timeOut) return;

祝你好运!