user7739271
user7739271

Reputation:

Can I re-draw a canvas image with its own image?

I'm learning to draw an image with canvas and getting a problem inside this example:

let img = new Image();
img.src = 'https://image.freepik.com/free-photo/hrc-siberian-tiger-2-jpg_21253111.jpg';

let a = function () {
    let c1 = document.getElementById('c1'),
        c2 = document.getElementById('c2');

    c1.width = c2.width = 150;
    c1.height = c2.width = 150;

    c1.getContext('2d').drawImage(img, 0, 0, 150, 150);
    c2.getContext('2d').drawImage(img, 0, 0, 150, 150);
};

let b = function () {
    let c2 = document.getElementById('c2');
    
    c2.width = 100;
    c2.height = 100;
    
    c2.getContext('2d').drawImage(c2, 0, 0, 100, 100);
};

let c = function () {
    let c1 = document.getElementById('c1'),
        c3 = document.getElementById('c3');
        
    c3.width = 100;
    c3.height = 100;
    
    c3.getContext('2d').drawImage(c1, 0, 0, 100, 100);
};

a();
b();
c();
<div>
  <canvas id="c1"></canvas>
</div>

<div>
  <canvas id="c2"></canvas>
</div>

<div>
  <canvas id="c3"></canvas>
</div>

Inside b function. I want to re-draw (resize) its own image with another size (changing width and height from 150 to 100). But it looks like it couldn't.

Then, I've tried to make another function (c). In this function, I've used the image of canvas c1 to re-draw image of canvas c3. That's ok.

So, my question is: Cannot canvas use its own image to draw an image for itself? (or maybe I've done something wrong)

Upvotes: 1

Views: 892

Answers (1)

zero298
zero298

Reputation: 26909

Edit: At first I thought that using an HTMLCanvasElement in the drawImage() call was an incorrect argument type. That was wrong, it's a valid argument. The actual issue was that the code was not waiting for the image to load.


You need to take a look at how you are getting your initial image data for your first canvas. I would not expect it to work because you could be drawing the image data from img before it is actually loaded. You need to attach callbacks to img to wait for it to finish loading the image and then draw that image on a canvas.

Consider my example below that includes an asynchronous way to load an image, how to draw one canvas in another, and how to draw text (just to show differences between canvases).

function loadImage(path) {
  return new Promise((resolve, reject) => {
    let img = new Image();
    img.addEventListener("load", () => {
      resolve(img);
    });
    img.addEventListener("error", (err) => {
      reject(err);
    });
    img.src = path;
  });
}


loadImage("https://cdn.sstatic.net/Sites/stackoverflow/img/sprites.svg")
  .then((img) => {
    let c1 = document.getElementById("c1"),
      c2 = document.getElementById("c2"),
      c1Ctx = c1.getContext("2d"),
      c2Ctx = c2.getContext("2d");
    c1Ctx.drawImage(img, 0, 0, 150, 150);
    c1Ctx.strokeText("I'm drawing on canvas 1", 25, 25);
    c2Ctx.drawImage(c1, 25, 25, 100, 100);
    c2Ctx.strokeText("I'm drawing on canvas 2", 25, 25);
  })
  .catch(console.error);
<canvas id="c1" width="150" height="150"></canvas>
<canvas id="c2" width="150" height="150"></canvas>


Another thing that you will likely run into since you want to be able to pull data out of your canvas is CORS issues. I point this out explicitly because the image that you are trying to draw onto your canvas is from a different domain (image.freepik.com in your example). Whenever you draw image data from another domain onto a canvas, that canvas becomes tainted an you can no longer use canvas' toBlob(), toDataURL(), or getImageData() methods. See: MDN: CORS enabled image.

Upvotes: 0

Related Questions