0

I am drawing canvas sin and adding movement to it

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;
  }

}

And everytime i am pressing button to draw it again canvas is redrawing it but it moves 2 times faster then before. I tried to do

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

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

  stopAnimation(req) {
    cancelAnimationFrame(req);
  }

with cancelAnimationFrame() hoping that it will get requestID to stop the ongoing animation but it didn't work.

  • *"I tried to do something with cancelAnimationFrame() but nothing worked'* Show us that, because it's how you would solve the problem. So we can help you figure out why it didn't if we see what you did. – T.J. Crowder Jun 08 '20 at 16:29
  • The edit shows you writing to a freestanding variable (`request`) and then later trying to use another freestanding variable with a different name (`req`). At a minimum, the names must match, and if this is instance-specific you need to make it an instance property. – T.J. Crowder Jun 08 '20 at 16:40

1 Answers1

0

Since drawWind sets up the next call every time it's called, it makes sense that when you call it from the click handler, now you have two series of it running in parallel and things go twice as fast.

You said you tried cancelAnimationFrame but didn't show us that code. That is indeed how you would deal with this:

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

Now, when the button click calls drawWind while it has an rAF callback scheduled, it cancels that callback and sets a new one. So you still only have the one series running.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Just got 1 more question. Why doesn't the animation stopes? If we are setting `rafHandle` to `requestAnimationFrame(this.drawWind.bind(this))` and the function repeats shouldn't `cancelAnimationFrame` stope it since it receives the previous callback number? – Ioannis Mikhailidis Jun 08 '20 at 17:10
  • @IoannisMikhaylidis - Because the next thing we do is schedule a new callback (which will schedule another one when called, which...). – T.J. Crowder Jun 08 '20 at 18:09