【问题标题】:How to prevent requestAnimationFrame from redrawing canvas more then one time after clicking the button?单击按钮后如何防止 requestAnimationFrame 重绘画布一次以上?
【发布时间】:2020-06-08 16:26:00
【问题描述】:

我正在画画布并添加动作

export class CanvasComponent implements OnInit {
  @ViewChild('canvas', { static: true })
  canvas: ElementRef<HTMLCanvasElement>;

  ctx: CanvasRenderingContext2D;

  winddrawvalue = 0;
  windvalue = 0;

  constructor() { }

  @Input() set speeddata(speed: number){
    this.windvalue = speed;
    this.drawWind();
  }

  ngOnInit(): void {
    this.ctx = this.canvas.nativeElement.getContext('2d');
  }

  drawWind() {
    requestAnimationFrame(this.drawWind.bind(this));
    const canvas = this.canvas.nativeElement;
    this.ctx.lineWidth = 2;
    this.ctx.clearRect(0, 0, canvas.width, canvas.height);
    this.ctx.beginPath();

    this.ctx.moveTo(-10, canvas.height / 2 - 12);
    for (let i = 0; i < canvas.width; i++) {
      this.ctx.lineTo(i, canvas.height / 2 - 12 + Math.sin(i * 0.04 + this.winddrawvalue) * 15);
    }

    this.ctx.moveTo(-10, canvas.height / 2);
    for (let i = 0; i < canvas.width; i++) {
      this.ctx.lineTo(i, canvas.height / 2 + Math.sin(i * 0.04 + this.winddrawvalue) * 15);
    }

    this.ctx.moveTo(-10, canvas.height / 2 + 12);
    for (let i = 0; i < canvas.width; i++) {
      this.ctx.lineTo(i, canvas.height / 2 + 12 + Math.sin(i * 0.04 + this.winddrawvalue) * 15);
    }

    this.ctx.stroke();
    this.winddrawvalue += this.windvalue;
  }

}

每次我按下按钮再次绘制它时,画布都会重新绘制它,但它的移动速度比以前快 2 倍。 我试着做

request = requestAnimationFrame(this.drawWind.bind(this));

  @Input() set speeddata(speed: number){
    this.windvalue = speed;
    this.stopAnimation(this.request);
    this.drawWind();
  }

  stopAnimation(req) {
    cancelAnimationFrame(req);
  }

cancelAnimationFrame() 希望它会获得 requestID 以停止正在进行的动画,但它没有工作。

【问题讨论】:

  • “我尝试用 cancelAnimationFrame() 做一些事情,但没有任何效果” 告诉我们,因为这是您解决问题的方法。所以我们可以帮助您找出原因如果我们看到你做了什么,它就没有了。
  • 编辑显示您写入一个独立变量 (request),然后尝试使用另一个名称不同的独立变量 (req)。至少,名称必须匹配,如果这是特定于实例的,则需要将其设为实例属性。

标签: angular typescript canvas requestanimationframe cancelanimationframe


【解决方案1】:

由于drawWind 每次调用它时都会设置下一个调用,所以当您从点击处理程序调用它时,现在您有两个系列并行运行并且速度是原来的两倍。

您说您尝试了cancelAnimationFrame,但没有向我们展示该代码。这确实是你处理这个问题的方式:

drawWind() {
  cancelAnimationFrame(this.rafHandle);
  this.rafHandle = requestAnimationFrame(this.drawWind.bind(this));

现在,当按钮单击调用 drawWind 而它有一个 rAF 回调计划时,它会取消该回调并设置一个新回调。所以你仍然只运行一个系列。

【讨论】:

  • 刚刚还有 1 个问题。为什么动画不停止?如果我们将rafHandle 设置为requestAnimationFrame(this.drawWind.bind(this)) 并且函数重复不应该cancelAnimationFrame 停止它,因为它收到了之前的回调号码?
  • @IoannisMikhaylidis - 因为我们接下来要做的是安排一个新的回调(它会在调用时安排另一个回调,...)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-13
  • 2011-09-02
  • 2011-07-08
  • 1970-01-01
  • 2020-10-09
  • 1970-01-01
相关资源
最近更新 更多