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.
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.