Why I need to press DRAW button two times to get Canvas and base64 formatted image

Viewed 29

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      button {
        padding: 10px 50px;
        cursor: pointer;
      }
      .custom {
        width: 200px;
        height: 200px;
      }
      .canvas-container {
        border: 5px solid #000;
        margin-bottom: 10px;
        margin-top: 10px;
      }
    </style>
    <script>
      const draw = () => {
        const availableImages = [1, 2];
        let canvas = document.querySelector("#screenShotCanvas");
        var context = canvas.getContext("2d");
        let image = document.querySelector("#cnimg");
        canvas.width = availableImages.length * 700;
        canvas.height = 450;
        var promises = availableImages.map((img, index) => {
          var imageEl = document.getElementById(`img${index + 1}`);
          imageEl.setAttribute("crossOrigin", "anonymous");
          imageEl.height = 450;
          imageEl.width = 700;
          context.drawImage(imageEl, index * 700, 0, 700, 450);
          return img;
        });

        Promise.all(promises)
          .then(() => {
            var canvasImg = canvas.toDataURL();
            console.log("canvasImg");
            console.log(canvasImg);
            image.src = canvasImg;
          })
          .catch((error) => {
            console.log("⚠️ERROR⚠️");
            console.error(error.message);
          });
      };
    </script>
  </head>
  <body>
    <button onclick="draw()">DRAW</button>
    <div class="canvas-container">
      <h2>Canvas image will show here once you click DRAW button</h2>
      <canvas id="screenShotCanvas"></canvas>
    </div>
    <div>
      <img
        class="custom"
        src="https://cdn.pixabay.com/photo/2016/02/05/19/51/stained-glass-1181864_960_720.jpg"
        id="img1"
      />
      <img
        class="custom"
        src="https://cdn.pixabay.com/photo/2018/10/08/13/05/hindu-3732713_960_720.jpg"
        id="img2"
      />
    </div>
    <div>
      <h2>Base 64 converted image will show here.</h2>
      <img src="" id="cnimg" alt="base64" />
    </div>
  </body>
</html>

In the above code snippet, there are two static images from pixabay.com.
When you press DRAW button, it will generate a canvas which is the combination of those two images.

After creating canvas, I converted it to base64 format to show in <img src="" id="cnimg" alt="base64" />.

But the problem is : I need to press DRAW button two times to get canvas and base64 formatted image.

If I remove imageEl.setAttribute("crossOrigin", "anonymous"); then I am getting canvas, but I am not getting base64 formatted image and also getting an error. Error :

Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

1 Answers

You can add the crossOrigin on the html and it will work, below is an example:

const draw = () => {
  const availableImages = [1, 2];
  let canvas = document.querySelector("#screenShotCanvas");
  var context = canvas.getContext("2d");
  canvas.width = availableImages.length * 100;

  var promises = availableImages.map((img, index) => {
    var imageEl = document.getElementById(`img${index + 1}`);
    context.drawImage(imageEl, index * 100, 0, 100, 100);
  });

  Promise.all(promises)
    .then(() => {
      document.querySelector("#cnimg").src = canvas.toDataURL()
    })
};
div>img {
  width: 50px
}
<button onclick="draw()">DRAW</button>
<div class="canvas-container">
  <canvas id="screenShotCanvas" height=100></canvas>
</div>
<div>
  <img id="img1" crossOrigin="anonymous" src="https://cdn.pixabay.com/photo/2016/02/05/19/51/stained-glass-1181864_960_720.jpg" />
  <img id="img2" crossOrigin="anonymous" src="https://cdn.pixabay.com/photo/2018/10/08/13/05/hindu-3732713_960_720.jpg" />
</div>
<img id="cnimg" alt="base64"  src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" />

My educated guess your original problem is that changing the crossOrigin in script affects the image, probably causes a reload, and when we try to draw the image has not reloaded, that is why it works the second time.

One improvement I added to your code was:
<img src="" id="cnimg" alt="base64" />
that will display I changed your src to a transparent 1x1 pixel image, to not show anything

I did reduced a lot of your code to just focus on the problem, you should do the same on your questions, minimal code makes more likely to get faster response

Related