1

I've been working on a little program that generates a finished image out of several layers. I need it to all be on one canvas so that I can save the final product as a single image. However, when I run my code, it draws the layers in a random order. If someone could please explain to me how to get the layers to render in order, I would really appreciate it!

function addimage(image, layer) {
var canvas = document.getElementById('paper'),
context = canvas.getContext('2d');

var img = new Image();
img.src = "Images/" + image;
img.onload = function(){
    if (image == "Khundii_Agouti_Basic.png"){
        context.globalCompositeOperation = "multiply";
    } else if (image == "Khundii_Agouti_Cinnamon.png"){
        context.globalCompositeOperation = "overlay";
    } else if (layer == "pattern1"){
        context.globalCompositeOperation = "overlay";
    } else {
        context.globalCompositeOperation = "source-over";
    }
    context.drawImage(img, 0, 0, 500, 500);
}
}

Above is the code that adds the image to the canvas

addimage(baseImage);
if (pattern1 == true)
    addimage(pattern1Image, "pattern1");
if (pattern2 == true)
    addimage(pattern2Image);
if (tint1 == true)
    addimage(tint1Image);
if (tint2 == true)
    addimage(tint2Image);
if (agouti == true)
    addimage(agoutiImage);
addimage(maneImage);
addimage(eyeImage);

addimage("Khundii_Line_Black.png");

And here is where it is called.

All of the code can be found here if you want to see more.

Yodra Gurl
  • 23
  • 5
  • Can you post your HTML, and maybe set up a snippet for people to troubleshoot with? That will help us recreate the issue and work a solution. Thanks! – Joel Hager Apr 26 '20 at 21:33

1 Answers1

1

The reasoning behind this seemingly random ordering is because of the load time before rendering images. Since loading is an asyncronous process, the computer goes through all of the images and starts loading them all in a row. Depending on the images, it may take the computer a little more time to load one of the first images compared to one of the last ones.

Now that we understand the problem, what are the potential fixes? The worst possible one is making the images load synchronously. I will leave a link here for reference, but it is almost never a good idea to do so. A better way of doing this is having a callback function for your addImage function. Something like this would do the trick:

function addimage(image, layer, callback) {
    var canvas = document.getElementById('paper'),
    context = canvas.getContext('2d');

    var img = new Image();
    img.src = "Images/" + image;
    img.onload = function(){
        if (image == "Khundii_Agouti_Basic.png"){
            context.globalCompositeOperation = "multiply";
        } else if (image == "Khundii_Agouti_Cinnamon.png"){
            context.globalCompositeOperation = "overlay";
        } else if (layer == "pattern1"){
            context.globalCompositeOperation = "overlay";
        } else {
            context.globalCompositeOperation = "source-over";
        }
        context.drawImage(img, 0, 0, 500, 500);
        callback();
    }
}

To use this just put all the code you would want to run afterward inside the callback function.

IndevSmiles
  • 737
  • 6
  • 17
  • The problem is that I need to be calling the addImage function quite a few times in a row, so with a callback like that I'd have to keep nesting different callbacks. – Yodra Gurl Apr 26 '20 at 22:49