Home > Net >  clear only certain components of a canvas
clear only certain components of a canvas

Time:11-11

I am creating a carousel slider with a canvas. For every new photo slide in, I would like to keep the previous one until the new one completely comes in.

I use requestAnimationFrame to do the sliding effect. Every time, I need to clear the canvas for the animation. But I would like to keep the previous image(drawing).

Here is an example of the effect but I do it in a very inefficient way. my javascript

window.onload = () => {
  let canvas = document.getElementById("myCanvas");
  let ctx = canvas.getContext("2d");

  let head = canvas.width;
  function draw1() {
    if (head > 0) {
      head = head - 10;
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      ctx.fillStyle = "rgba(0, 255, 255,1)";
      ctx.fillRect(head, 0, canvas.width - head, canvas.height);
      window.requestAnimationFrame(draw1);
    }
  }

  function draw2() {
    if (head > 0) {
      head = head - 10;
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // Draw the previous canvas again for every update
      ctx.fillStyle = "rgba(0, 255, 255,1)";
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      ctx.fillStyle = "rgba(255, 0, 255,1)";
      ctx.fillRect(head, 0, canvas.width - head, canvas.height);
      window.requestAnimationFrame(draw2);
    }
  }

  function draw3() {
    if (head > 0) {
      head = head - 10;
      ctx.clearRect(0, 0, canvas.width, canvas.height);

      // Draw the previous canvas again for every update
      ctx.fillStyle = "rgba(255, 0, 255,1)";
      ctx.fillRect(0, 0, canvas.width, canvas.height);

      ctx.fillStyle = "rgba(255, 255, 0,1)";
      ctx.fillRect(head, 0, canvas.width - head, canvas.height);
      window.requestAnimationFrame(draw3);
    }
  }
  head = canvas.width;
  draw1();

  setTimeout(() => {
    head = canvas.width;
    draw2();
  }, 2000);

  setTimeout(() => {
    head = canvas.width;
    draw3();
  }, 4000);
};

Any help is appreciated. Thanks.

CodePudding user response:

For your case you can draw over the previous image without clearing the canvas

Show code snippet

window.onload = () => {
  let canvas = document.getElementById('myCanvas')
  let ctx = canvas.getContext('2d')
  let head = canvas.width

  function drawImage(current) {
    if (head > 0) {
      head = head - 10
      ctx.drawImage(current, head, 0, canvas.width, canvas.height)
      window.requestAnimationFrame(() => drawImage(current))
    }
  }

  const empty = new Image()

  const img1 = new Image()
  img1.src =
    'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAegr5NqpnuNQdxthB4Ys5O_uiyEqs-CQp6w&usqp=CAU'


  const img2 = new Image()
  img2.src =
    'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSHFvenDq4nX-LgsmrRPamE9i-NMBkefW7Lzg&usqp=CAU'

  const img3 = new Image()
  img3.src =
    'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSyiU9Jkual4WsPg38vFfxvYgDQlUdzOOecVg&usqp=CAU'

  head = canvas.width

  img1.onload = () => {
    drawImage(img1)
  }

  img2.onload = () => {
    setTimeout(() => {
      head = canvas.width
      drawImage(img2)
    }, 2000)
  }

  img3.onload = () => {
    setTimeout(() => {
      head = canvas.width
      drawImage(img3)
    }, 4000)
  }
}
body {
  display: flex;
  justify-content: center;
  align-items: center;
}

canvas {
  border: 1px solid #000000;
}
<canvas id="myCanvas" width="440" height="160"></canvas>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

EDIT:

For transparent images you can clear just the part of the canvas where the new transparent image is showing. So something like:

ctx.clearRect(head, 0, canvas.width - head, canvas.height)

Here is an example:

Show code snippet

window.onload = () => {
  let canvas = document.getElementById('myCanvas')
  let ctx = canvas.getContext('2d')
  let head = canvas.width

  function drawImage(current) {
    if (head > 0) {
      head = head - 10
      ctx.clearRect(head, 0, canvas.width - head, canvas.height)
      ctx.drawImage(current, head, 0, canvas.width, canvas.height)
      window.requestAnimationFrame(() => drawImage(current))
    }
  }

  const empty = new Image()

  const img1 = new Image()
  img1.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAegr5NqpnuNQdxthB4Ys5O_uiyEqs-CQp6w&usqp=CAU'

  const img2 = new Image()
  img2.src = 'https://api.iconify.design/foundation:social-github.svg'
  const img3 = new Image()
  img3.src = 'https://api.iconify.design/foundation:social-twitter.svg'

  head = canvas.width

  img1.onload = () => {
    drawImage(img1)
  }

  img2.onload = () => {
    setTimeout(() => {
      head = canvas.width
      drawImage(img2)
    }, 2000)
  }

  img3.onload = () => {
    setTimeout(() => {
      head = canvas.width
      drawImage(img3)
    }, 4000)
  }
}
body {
  display: flex;
  justify-content: center;
  align-items: center;
}

canvas {
  border: 1px solid #000000;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
}

canvas {
  border: 1px solid #000000;
}
<canvas id="myCanvas" width="440" height="170"></canvas>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

And for having a transparent image on top of the previous image you can do something like this:

window.onload = () => {
  let canvas = document.getElementById('myCanvas')
  let ctx = canvas.getContext('2d')
  let head = canvas.width

  function drawImage(prev, current) {
    if (head > 0) {
      head = head - 10
      ctx.clearRect(head, 0, canvas.width - head, canvas.height)
      ctx.drawImage(prev, 0, 0, canvas.width, canvas.height)
      ctx.drawImage(current, head, 0, canvas.width, canvas.height)
      window.requestAnimationFrame(() => drawImage(prev, current))
    }
  }

  const empty = new Image()

  const img1 = new Image()
  img1.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQAegr5NqpnuNQdxthB4Ys5O_uiyEqs-CQp6w&usqp=CAU'

  const img2 = new Image()
  img2.src = 'https://api.iconify.design/foundation:social-github.svg'

  const img3 = new Image()
  img3.src = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSHFvenDq4nX-LgsmrRPamE9i-NMBkefW7Lzg&usqp=CAU'

  const img4 = new Image()
  img4.src = 'https://api.iconify.design/foundation:social-twitter.svg'



  head = canvas.width

  img1.onload = () => {
    drawImage(empty, img1)
  }

  img2.onload = () => {
    setTimeout(() => {
      head = canvas.width
      drawImage(img1, img2)
    }, 2000)
  }

  img3.onload = () => {
    setTimeout(() => {
      head = canvas.width
      drawImage(img2, img3)
    }, 5000);
  }


  img4.onload = () => {
    setTimeout(() => {
      head = canvas.width
      drawImage(img3, img4)
    }, 8000);
  }

}
body {
  display: flex;
  justify-content: center;
  align-items: center;
}

canvas {
  border: 1px solid #000000;
}
<canvas id="myCanvas" width="440" height="170"></canvas>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related