Home > Net >  HTML canvas drawImage stacks images when changing source
HTML canvas drawImage stacks images when changing source

Time:07-12

I'm trying to show an animation when the user scrolls on my page. I've followed the following guide to make an "Apple like animation", and tried with my own image sequence.

This is the code I'm using:

ngOnInit(): void {
  const canvas = <HTMLCanvasElement> document.getElementById("canvas1")!;
  const context = canvas.getContext("2d")!;

  canvas.width = 1158;
  canvas.height = 770;

  const img = new Image()
  img.onload = () => {
    context.drawImage(img, 0, 0, canvas.width, canvas.height);
  }
  img.src = this.currentFrame(1);

  window.addEventListener('scroll', () => {
    const scrollLength = window.scrollY;
    const maxScrollTop = this.document.body.scrollHeight - window.innerHeight;
    const scrollFraction = scrollLength / maxScrollTop;
    let frameIndex = Math.min(
      this.frameCount,
      Math.floor(scrollFraction * this.frameCount)
    );
    if (frameIndex   1 > this.frameCount) frameIndex = this.frameCount   2;
    requestAnimationFrame(() => this.updateImage(frameIndex, canvas, context, img));
  });
  this.preloadImages();
}

updateImage(index: number, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, img: HTMLImageElement) {
  if (index == 0 || index > this.frameCount) {
    context.clearRect(0, 0, img.width , img.height);
  } else {
    img.src = this.currentFrame(index);
    context.drawImage(img, 0, 0, canvas.width, canvas.height);
  }
}

CodePudding user response:

You likely need to clear it before adding the new image. Try changing this function:

updateImage(index: number, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, img: HTMLImageElement) {
  if (index == 0 || index > this.frameCount) {
    context.clearRect(0, 0, img.width , img.height);
  } else {
    context.clearRect(0, 0, img.width , img.height);
    img.src = this.currentFrame(index);
    context.drawImage(img, 0, 0, canvas.width, canvas.height);
  }
}

CodePudding user response:

It was actually the right thought Zorion had with his answer

But when doing it like that, the canvas will turn blank until the next image had been loaded, making it feel laggy and chuggy. The solution to this is to clear the canvas once the next image had been loaded.

Adding the context.clearRect in the img.onload function:

img.onload = () => {
  context.clearRect(0, 0, img.width , img.height);
  context.drawImage(img, 0, 0, canvas.width, canvas.height);
}
  • Related