skip to Main Content

I’m trying to draw two images on the same canvas, but the second image being loaded is "erasing" the first. The images are the same size and they complete each other.

HTML:

<canvas id="canvas style="width: 400px"/>
<img id="img1" src="myImage1" />
<img id="img2" src="myImage2" />

JS:

var canvas = document.getElementByID("canvas");
var ctx = canvas.getContext('2d');

var img1 = document.getElementByID("img1");
var img2 = document.getElementByID("img2");

img1.onload = function(){
 canvas.width = img1.naturalWidth;
 canvas.height = img1.naturalHeight;

 ctx.drawImage(img1, 0, 0);
}

img2.onload = function(){
 canvas.width = img2.naturalWidth;
 canvas.height = img2.naturalHeight;

 ctx.drawImage(img2, 0, 0);
}

2

Answers


  1. Changing the size of the canvas clears the context.

    If you’re sure the images align, all you have to do is make sure you only initialize once using the dimensions of whichever image loads first:

    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext('2d');
    
    var img1 = document.getElementById("img1");
    var img2 = document.getElementById("img2");
    
    var didInit = false;
    function init(img) {
      canvas.width = img.naturalWidth;
      canvas.height = img.naturalHeight;
      didInit = true;
    }
    
    img1.onload = function(){
     if (!didInit) init(img1);
     ctx.drawImage(img1, 0, 0);
    }
    
    img2.onload = function(){
     if (!didInit) init(img2);
     ctx.drawImage(img2, 0, 0);
    }
    canvas {
      display: block;
      border: 1px solid lime;
    }
    
    img {
      visibility: hidden;
    }
    <canvas id="canvas"></canvas>
    
    <img id="img1" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAImSURBVHgB7daxDcNADARBvqH+W343IG3MYKYEAgvemZk7bHKGNX4DfBIIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIhGdg5gyvHGafO2xxTSwIAtnFR19GIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBALhGba5wxb3D2JQBpHWtsxvAAAAAElFTkSuQmCC" alt="black" />
    
    <img id="img2" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAIrSURBVHgB7daxDcMwDABBOvD+KyuB6/hrFnegFpDwEK9hlfMMS5zPAK8EAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAuEemDnDP+c6LmeV6xm2sGJBEMgufvNlBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQ7t85wxbeYpkv/gALi57sGR8AAAAASUVORK5CYII=" alt="red" />

    Alternatively, you could wait for all images to be loaded, find the largest width and height dimension, set the canvas size and only then draw all the images to it.

    const canvas = document.getElementById("canvas");
    const ctx = canvas.getContext("2d");
    
    
    const loadedImages = [];
    const drawImagesToPage = () => {
      let maxW = 0;
      let maxH = 0;
      
      for (const img of loadedImages) {
        maxW = Math.max(maxW, img.naturalWidth);
        maxH = Math.max(maxH, img.naturalHeight);
      }
      
      canvas.width = maxW;
      canvas.height = maxH;
      
      for (const img of loadedImages) {
        ctx.drawImage(img, 0, 0);
      }
    }
    
    document
      .querySelectorAll("img")
      .forEach((img, idx, all) => {
        loadedImages.push(img);
        
        if (loadedImages.length === all.length) {
          drawImagesToPage();
        }
      });
    canvas {
      display: block;
      border: 1px solid lime;
    }
    
    img {
      visibility: hidden;
    }
    <canvas id="canvas"></canvas>
    
    <img id="img1" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAImSURBVHgB7daxDcNADARBvqH+W343IG3MYKYEAgvemZk7bHKGNX4DfBIIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIBIFAEAgEgUAQCASBQBAIhGdg5gyvHGafO2xxTSwIAtnFR19GIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBALhGba5wxb3D2JQBpHWtsxvAAAAAElFTkSuQmCC" alt="black" />
    
    <img id="img2" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAIrSURBVHgB7daxDcMwDABBOvD+KyuB6/hrFnegFpDwEK9hlfMMS5zPAK8EAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAuEemDnDP+c6LmeV6xm2sGJBEMgufvNlBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQBAJBIBAEAkEgEAQCQSAQ7t85wxbeYpkv/gALi57sGR8AAAAASUVORK5CYII=" alt="red" />
    Login or Signup to reply.
  2. You can’t change height or width because canvas will be cleared

    Better wait for both images to load and then set dimensions

    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    
    var img1 = document.getElementById("img1");
    var img2 = document.getElementById("img2");
    
    ctx.fillStyle = "red";
    ctx.fillRect(0, 0, 300, 300);
    
    Promise.all([
      new Promise((r) => {
        img1.onload = function() {
          r(img1);
        };
      }),
      new Promise((r) => {
        img2.onload = function() {
          r(img2);
        };
      })
    ]).then(([img1, img2]) => {
      const width = Math.max(img1.naturalWidth, img2.naturalWidth);
      const height = Math.max(img1.naturalHeight, img2.naturalHeight);
      
      canvas.width = width;
      canvas.height = height;
      ctx.drawImage(img1, 0, 0);
      ctx.drawImage(img2, 0, 0);
    });
    <!DOCTYPE html>
    <html>
    
    <head>
      <title>Parcel Sandbox</title>
      <meta charset="UTF-8" />
    </head>
    
    <body>
      <canvas id="canvas"></canvas>
      <img id="img1" src="https://i.imgur.com/hXp1nj4.png" />
      <img id="img2" src="https://i.imgur.com/2XpTBZa.png" />
    </body>
    
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search