How do I make sure that images load in the right order on the canvas?









up vote
1
down vote

favorite
1












I have the following JavaScript file with a function called menu that calls the draw function 4 different times to display 4 different images on the screen.



I need to display them in the order they are coded in, but every time I refresh I get something different. I understand that this is most likely because some of the images load faster than others.



I have looked up some other examples of this on the site and the solution seems to be drawing the images only when all of them are loaded first, however I can't get that to work.



Is there another way?



var cvs = document.getElementById("canvas");
var ctx = cvs.getContext("2d");
var audio = new Audio('sounds/sound.ogg');
cvs.addEventListener("click", function()
audio.play();
);
var logoSound;

ctx.fillStyle= "#87ceeb";
ctx.fillRect(0,0,1330,800);

function draw(src, a, b)
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function()
ctx.drawImage(img, x, y);
;
img.src = src;


function menu()
draw("images/clouds.png", 0, 300);
draw("images/background.png", 0, 360);
draw("images/display.png", 410, 0);
draw("images/plank.png", 405, 300);


menu();


Update



async function draw(src,x,y) 
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function()
ctx.drawImage(img,x,y);
;
img.src = src;


// main
(async function menu ()
await draw("images/clouds.png", 0, 300);
await draw("images/background.png", 0, 360);
await draw("images/display.png", 410, 0);
await draw("images/plank.png", 405, 300);
await draw("images/info.png", 1195, 660);
());

function cloud2()
ctx.drawImage(cloud, speed, 0);

cvs.requestAnimationFrame(cloud);


menu();









share|improve this question























  • Why not something that draws the next image from the onload handler?
    – Dave Newton
    Nov 10 at 3:57










  • Do you mind giving a quick example of how I could do that for multiple images? Thanks.
    – Zach
    Nov 10 at 3:58










  • shrug There are several ways, off the top of my head, an array of objects describing the image, get the first one and save off the rest, in onload all the same function with the remaining array elements. If the array is empty, return and do nothing; normal recursive stuff. Not terribly elegant, but meh.
    – Dave Newton
    Nov 10 at 4:44














up vote
1
down vote

favorite
1












I have the following JavaScript file with a function called menu that calls the draw function 4 different times to display 4 different images on the screen.



I need to display them in the order they are coded in, but every time I refresh I get something different. I understand that this is most likely because some of the images load faster than others.



I have looked up some other examples of this on the site and the solution seems to be drawing the images only when all of them are loaded first, however I can't get that to work.



Is there another way?



var cvs = document.getElementById("canvas");
var ctx = cvs.getContext("2d");
var audio = new Audio('sounds/sound.ogg');
cvs.addEventListener("click", function()
audio.play();
);
var logoSound;

ctx.fillStyle= "#87ceeb";
ctx.fillRect(0,0,1330,800);

function draw(src, a, b)
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function()
ctx.drawImage(img, x, y);
;
img.src = src;


function menu()
draw("images/clouds.png", 0, 300);
draw("images/background.png", 0, 360);
draw("images/display.png", 410, 0);
draw("images/plank.png", 405, 300);


menu();


Update



async function draw(src,x,y) 
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function()
ctx.drawImage(img,x,y);
;
img.src = src;


// main
(async function menu ()
await draw("images/clouds.png", 0, 300);
await draw("images/background.png", 0, 360);
await draw("images/display.png", 410, 0);
await draw("images/plank.png", 405, 300);
await draw("images/info.png", 1195, 660);
());

function cloud2()
ctx.drawImage(cloud, speed, 0);

cvs.requestAnimationFrame(cloud);


menu();









share|improve this question























  • Why not something that draws the next image from the onload handler?
    – Dave Newton
    Nov 10 at 3:57










  • Do you mind giving a quick example of how I could do that for multiple images? Thanks.
    – Zach
    Nov 10 at 3:58










  • shrug There are several ways, off the top of my head, an array of objects describing the image, get the first one and save off the rest, in onload all the same function with the remaining array elements. If the array is empty, return and do nothing; normal recursive stuff. Not terribly elegant, but meh.
    – Dave Newton
    Nov 10 at 4:44












up vote
1
down vote

favorite
1









up vote
1
down vote

favorite
1






1





I have the following JavaScript file with a function called menu that calls the draw function 4 different times to display 4 different images on the screen.



I need to display them in the order they are coded in, but every time I refresh I get something different. I understand that this is most likely because some of the images load faster than others.



I have looked up some other examples of this on the site and the solution seems to be drawing the images only when all of them are loaded first, however I can't get that to work.



Is there another way?



var cvs = document.getElementById("canvas");
var ctx = cvs.getContext("2d");
var audio = new Audio('sounds/sound.ogg');
cvs.addEventListener("click", function()
audio.play();
);
var logoSound;

ctx.fillStyle= "#87ceeb";
ctx.fillRect(0,0,1330,800);

function draw(src, a, b)
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function()
ctx.drawImage(img, x, y);
;
img.src = src;


function menu()
draw("images/clouds.png", 0, 300);
draw("images/background.png", 0, 360);
draw("images/display.png", 410, 0);
draw("images/plank.png", 405, 300);


menu();


Update



async function draw(src,x,y) 
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function()
ctx.drawImage(img,x,y);
;
img.src = src;


// main
(async function menu ()
await draw("images/clouds.png", 0, 300);
await draw("images/background.png", 0, 360);
await draw("images/display.png", 410, 0);
await draw("images/plank.png", 405, 300);
await draw("images/info.png", 1195, 660);
());

function cloud2()
ctx.drawImage(cloud, speed, 0);

cvs.requestAnimationFrame(cloud);


menu();









share|improve this question















I have the following JavaScript file with a function called menu that calls the draw function 4 different times to display 4 different images on the screen.



I need to display them in the order they are coded in, but every time I refresh I get something different. I understand that this is most likely because some of the images load faster than others.



I have looked up some other examples of this on the site and the solution seems to be drawing the images only when all of them are loaded first, however I can't get that to work.



Is there another way?



var cvs = document.getElementById("canvas");
var ctx = cvs.getContext("2d");
var audio = new Audio('sounds/sound.ogg');
cvs.addEventListener("click", function()
audio.play();
);
var logoSound;

ctx.fillStyle= "#87ceeb";
ctx.fillRect(0,0,1330,800);

function draw(src, a, b)
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function()
ctx.drawImage(img, x, y);
;
img.src = src;


function menu()
draw("images/clouds.png", 0, 300);
draw("images/background.png", 0, 360);
draw("images/display.png", 410, 0);
draw("images/plank.png", 405, 300);


menu();


Update



async function draw(src,x,y) 
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image();
img.onload = function()
ctx.drawImage(img,x,y);
;
img.src = src;


// main
(async function menu ()
await draw("images/clouds.png", 0, 300);
await draw("images/background.png", 0, 360);
await draw("images/display.png", 410, 0);
await draw("images/plank.png", 405, 300);
await draw("images/info.png", 1195, 660);
());

function cloud2()
ctx.drawImage(cloud, speed, 0);

cvs.requestAnimationFrame(cloud);


menu();






javascript image canvas






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 10 at 4:25

























asked Nov 10 at 3:51









Zach

242




242











  • Why not something that draws the next image from the onload handler?
    – Dave Newton
    Nov 10 at 3:57










  • Do you mind giving a quick example of how I could do that for multiple images? Thanks.
    – Zach
    Nov 10 at 3:58










  • shrug There are several ways, off the top of my head, an array of objects describing the image, get the first one and save off the rest, in onload all the same function with the remaining array elements. If the array is empty, return and do nothing; normal recursive stuff. Not terribly elegant, but meh.
    – Dave Newton
    Nov 10 at 4:44
















  • Why not something that draws the next image from the onload handler?
    – Dave Newton
    Nov 10 at 3:57










  • Do you mind giving a quick example of how I could do that for multiple images? Thanks.
    – Zach
    Nov 10 at 3:58










  • shrug There are several ways, off the top of my head, an array of objects describing the image, get the first one and save off the rest, in onload all the same function with the remaining array elements. If the array is empty, return and do nothing; normal recursive stuff. Not terribly elegant, but meh.
    – Dave Newton
    Nov 10 at 4:44















Why not something that draws the next image from the onload handler?
– Dave Newton
Nov 10 at 3:57




Why not something that draws the next image from the onload handler?
– Dave Newton
Nov 10 at 3:57












Do you mind giving a quick example of how I could do that for multiple images? Thanks.
– Zach
Nov 10 at 3:58




Do you mind giving a quick example of how I could do that for multiple images? Thanks.
– Zach
Nov 10 at 3:58












shrug There are several ways, off the top of my head, an array of objects describing the image, get the first one and save off the rest, in onload all the same function with the remaining array elements. If the array is empty, return and do nothing; normal recursive stuff. Not terribly elegant, but meh.
– Dave Newton
Nov 10 at 4:44




shrug There are several ways, off the top of my head, an array of objects describing the image, get the first one and save off the rest, in onload all the same function with the remaining array elements. If the array is empty, return and do nothing; normal recursive stuff. Not terribly elegant, but meh.
– Dave Newton
Nov 10 at 4:44












2 Answers
2






active

oldest

votes

















up vote
0
down vote













You could make your draw function asynchronous. The setTimeout call is a simulation of your asynchronous on load handler.



 async function draw (msg) 
return new Promise ((resolve, reject) =>
let randomDelay = Math.floor(Math.random() * 3000);
setTimeout(() =>
resolve(msg);
, randomDelay);
);


(async function ()
console.log(await draw(1));
console.log(await draw(2));
console.log(await draw(3));
console.log(await draw(4));
());


Which would guarantee the drawing order.



output is:
1
2
3
4






share|improve this answer






















  • I updated my answer to wrap the await calls in an async function. await can only be used inside of async functions. I found this tutorial helpful: javascript.info/async-await
    – VorpalSword
    Nov 10 at 4:19










  • I did another update, still not sure if that is correct. Am I invoking it correctly?
    – Zach
    Nov 10 at 4:26










  • draw isn't returning anything useful for await to use; you'd need to resolve a promise in the onload event.
    – Dave Newton
    Nov 10 at 4:42










  • I got off my phone and actually tested this code :-)async function draw (msg) return new Promise ((resolve, reject) => let randomDelay = Math.floor(Math.random() * 3000); setTimeout(() => resolve(msg); , randomDelay); ); (async function () console.log(await draw(1)); console.log(await draw(2)); console.log(await draw(3)); console.log(await draw(4)); ());
    – VorpalSword
    Nov 10 at 4:49











  • @DaveNewton thanks Dave - I fixed my answer and actually tested it on a proper computer. My downfall the first time was thinking I could peck working code into an iPhone. It turns out I can't. Mea maxima culpa.
    – VorpalSword
    Nov 10 at 4:57

















up vote
0
down vote













Drawing an image on a canvas is a synchronous operation, what is not, is to load these images.



So split your logic in 1.Loading, then 2.Drawing



The loading part will just create as many <img> elements as you need to be drawn, operation greatly cleaned up thanks to Promises.



Once that's done, the drawing part will just iterate over the images and draw them:






const ctx = canvas.getContext('2d');

function loadImages(urls)
return Promise.all(urls.map(loadImage));


function loadImage(url)
return new Promise((res, rej) => Object.assign((new Image()),
src: url,
onload: function(e)res(this),
onerror: rej
));


function drawImages(images)
images.forEach((img, i) => ctx.drawImage(img, i * 50, 0));


async function begin() 
// build up our array of urls
const urls = Array.from(
length: 10
, () => 'https://lorempixel.com/50/50?' + Math.random());
// load them all
const images = await loadImages(urls);
// draw them all
drawImages(images);


begin().catch(console.error)

<canvas id="canvas" width="500" height="50"></canvas>





Note that it is the basic operations when external assets are required:



  • Load all required assets.

  • Then start using them.





share|improve this answer




















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53235858%2fhow-do-i-make-sure-that-images-load-in-the-right-order-on-the-canvas%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    0
    down vote













    You could make your draw function asynchronous. The setTimeout call is a simulation of your asynchronous on load handler.



     async function draw (msg) 
    return new Promise ((resolve, reject) =>
    let randomDelay = Math.floor(Math.random() * 3000);
    setTimeout(() =>
    resolve(msg);
    , randomDelay);
    );


    (async function ()
    console.log(await draw(1));
    console.log(await draw(2));
    console.log(await draw(3));
    console.log(await draw(4));
    ());


    Which would guarantee the drawing order.



    output is:
    1
    2
    3
    4






    share|improve this answer






















    • I updated my answer to wrap the await calls in an async function. await can only be used inside of async functions. I found this tutorial helpful: javascript.info/async-await
      – VorpalSword
      Nov 10 at 4:19










    • I did another update, still not sure if that is correct. Am I invoking it correctly?
      – Zach
      Nov 10 at 4:26










    • draw isn't returning anything useful for await to use; you'd need to resolve a promise in the onload event.
      – Dave Newton
      Nov 10 at 4:42










    • I got off my phone and actually tested this code :-)async function draw (msg) return new Promise ((resolve, reject) => let randomDelay = Math.floor(Math.random() * 3000); setTimeout(() => resolve(msg); , randomDelay); ); (async function () console.log(await draw(1)); console.log(await draw(2)); console.log(await draw(3)); console.log(await draw(4)); ());
      – VorpalSword
      Nov 10 at 4:49











    • @DaveNewton thanks Dave - I fixed my answer and actually tested it on a proper computer. My downfall the first time was thinking I could peck working code into an iPhone. It turns out I can't. Mea maxima culpa.
      – VorpalSword
      Nov 10 at 4:57














    up vote
    0
    down vote













    You could make your draw function asynchronous. The setTimeout call is a simulation of your asynchronous on load handler.



     async function draw (msg) 
    return new Promise ((resolve, reject) =>
    let randomDelay = Math.floor(Math.random() * 3000);
    setTimeout(() =>
    resolve(msg);
    , randomDelay);
    );


    (async function ()
    console.log(await draw(1));
    console.log(await draw(2));
    console.log(await draw(3));
    console.log(await draw(4));
    ());


    Which would guarantee the drawing order.



    output is:
    1
    2
    3
    4






    share|improve this answer






















    • I updated my answer to wrap the await calls in an async function. await can only be used inside of async functions. I found this tutorial helpful: javascript.info/async-await
      – VorpalSword
      Nov 10 at 4:19










    • I did another update, still not sure if that is correct. Am I invoking it correctly?
      – Zach
      Nov 10 at 4:26










    • draw isn't returning anything useful for await to use; you'd need to resolve a promise in the onload event.
      – Dave Newton
      Nov 10 at 4:42










    • I got off my phone and actually tested this code :-)async function draw (msg) return new Promise ((resolve, reject) => let randomDelay = Math.floor(Math.random() * 3000); setTimeout(() => resolve(msg); , randomDelay); ); (async function () console.log(await draw(1)); console.log(await draw(2)); console.log(await draw(3)); console.log(await draw(4)); ());
      – VorpalSword
      Nov 10 at 4:49











    • @DaveNewton thanks Dave - I fixed my answer and actually tested it on a proper computer. My downfall the first time was thinking I could peck working code into an iPhone. It turns out I can't. Mea maxima culpa.
      – VorpalSword
      Nov 10 at 4:57












    up vote
    0
    down vote










    up vote
    0
    down vote









    You could make your draw function asynchronous. The setTimeout call is a simulation of your asynchronous on load handler.



     async function draw (msg) 
    return new Promise ((resolve, reject) =>
    let randomDelay = Math.floor(Math.random() * 3000);
    setTimeout(() =>
    resolve(msg);
    , randomDelay);
    );


    (async function ()
    console.log(await draw(1));
    console.log(await draw(2));
    console.log(await draw(3));
    console.log(await draw(4));
    ());


    Which would guarantee the drawing order.



    output is:
    1
    2
    3
    4






    share|improve this answer














    You could make your draw function asynchronous. The setTimeout call is a simulation of your asynchronous on load handler.



     async function draw (msg) 
    return new Promise ((resolve, reject) =>
    let randomDelay = Math.floor(Math.random() * 3000);
    setTimeout(() =>
    resolve(msg);
    , randomDelay);
    );


    (async function ()
    console.log(await draw(1));
    console.log(await draw(2));
    console.log(await draw(3));
    console.log(await draw(4));
    ());


    Which would guarantee the drawing order.



    output is:
    1
    2
    3
    4







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Nov 10 at 4:53

























    answered Nov 10 at 4:00









    VorpalSword

    4111314




    4111314











    • I updated my answer to wrap the await calls in an async function. await can only be used inside of async functions. I found this tutorial helpful: javascript.info/async-await
      – VorpalSword
      Nov 10 at 4:19










    • I did another update, still not sure if that is correct. Am I invoking it correctly?
      – Zach
      Nov 10 at 4:26










    • draw isn't returning anything useful for await to use; you'd need to resolve a promise in the onload event.
      – Dave Newton
      Nov 10 at 4:42










    • I got off my phone and actually tested this code :-)async function draw (msg) return new Promise ((resolve, reject) => let randomDelay = Math.floor(Math.random() * 3000); setTimeout(() => resolve(msg); , randomDelay); ); (async function () console.log(await draw(1)); console.log(await draw(2)); console.log(await draw(3)); console.log(await draw(4)); ());
      – VorpalSword
      Nov 10 at 4:49











    • @DaveNewton thanks Dave - I fixed my answer and actually tested it on a proper computer. My downfall the first time was thinking I could peck working code into an iPhone. It turns out I can't. Mea maxima culpa.
      – VorpalSword
      Nov 10 at 4:57
















    • I updated my answer to wrap the await calls in an async function. await can only be used inside of async functions. I found this tutorial helpful: javascript.info/async-await
      – VorpalSword
      Nov 10 at 4:19










    • I did another update, still not sure if that is correct. Am I invoking it correctly?
      – Zach
      Nov 10 at 4:26










    • draw isn't returning anything useful for await to use; you'd need to resolve a promise in the onload event.
      – Dave Newton
      Nov 10 at 4:42










    • I got off my phone and actually tested this code :-)async function draw (msg) return new Promise ((resolve, reject) => let randomDelay = Math.floor(Math.random() * 3000); setTimeout(() => resolve(msg); , randomDelay); ); (async function () console.log(await draw(1)); console.log(await draw(2)); console.log(await draw(3)); console.log(await draw(4)); ());
      – VorpalSword
      Nov 10 at 4:49











    • @DaveNewton thanks Dave - I fixed my answer and actually tested it on a proper computer. My downfall the first time was thinking I could peck working code into an iPhone. It turns out I can't. Mea maxima culpa.
      – VorpalSword
      Nov 10 at 4:57















    I updated my answer to wrap the await calls in an async function. await can only be used inside of async functions. I found this tutorial helpful: javascript.info/async-await
    – VorpalSword
    Nov 10 at 4:19




    I updated my answer to wrap the await calls in an async function. await can only be used inside of async functions. I found this tutorial helpful: javascript.info/async-await
    – VorpalSword
    Nov 10 at 4:19












    I did another update, still not sure if that is correct. Am I invoking it correctly?
    – Zach
    Nov 10 at 4:26




    I did another update, still not sure if that is correct. Am I invoking it correctly?
    – Zach
    Nov 10 at 4:26












    draw isn't returning anything useful for await to use; you'd need to resolve a promise in the onload event.
    – Dave Newton
    Nov 10 at 4:42




    draw isn't returning anything useful for await to use; you'd need to resolve a promise in the onload event.
    – Dave Newton
    Nov 10 at 4:42












    I got off my phone and actually tested this code :-)async function draw (msg) return new Promise ((resolve, reject) => let randomDelay = Math.floor(Math.random() * 3000); setTimeout(() => resolve(msg); , randomDelay); ); (async function () console.log(await draw(1)); console.log(await draw(2)); console.log(await draw(3)); console.log(await draw(4)); ());
    – VorpalSword
    Nov 10 at 4:49





    I got off my phone and actually tested this code :-)async function draw (msg) return new Promise ((resolve, reject) => let randomDelay = Math.floor(Math.random() * 3000); setTimeout(() => resolve(msg); , randomDelay); ); (async function () console.log(await draw(1)); console.log(await draw(2)); console.log(await draw(3)); console.log(await draw(4)); ());
    – VorpalSword
    Nov 10 at 4:49













    @DaveNewton thanks Dave - I fixed my answer and actually tested it on a proper computer. My downfall the first time was thinking I could peck working code into an iPhone. It turns out I can't. Mea maxima culpa.
    – VorpalSword
    Nov 10 at 4:57




    @DaveNewton thanks Dave - I fixed my answer and actually tested it on a proper computer. My downfall the first time was thinking I could peck working code into an iPhone. It turns out I can't. Mea maxima culpa.
    – VorpalSword
    Nov 10 at 4:57












    up vote
    0
    down vote













    Drawing an image on a canvas is a synchronous operation, what is not, is to load these images.



    So split your logic in 1.Loading, then 2.Drawing



    The loading part will just create as many <img> elements as you need to be drawn, operation greatly cleaned up thanks to Promises.



    Once that's done, the drawing part will just iterate over the images and draw them:






    const ctx = canvas.getContext('2d');

    function loadImages(urls)
    return Promise.all(urls.map(loadImage));


    function loadImage(url)
    return new Promise((res, rej) => Object.assign((new Image()),
    src: url,
    onload: function(e)res(this),
    onerror: rej
    ));


    function drawImages(images)
    images.forEach((img, i) => ctx.drawImage(img, i * 50, 0));


    async function begin() 
    // build up our array of urls
    const urls = Array.from(
    length: 10
    , () => 'https://lorempixel.com/50/50?' + Math.random());
    // load them all
    const images = await loadImages(urls);
    // draw them all
    drawImages(images);


    begin().catch(console.error)

    <canvas id="canvas" width="500" height="50"></canvas>





    Note that it is the basic operations when external assets are required:



    • Load all required assets.

    • Then start using them.





    share|improve this answer
























      up vote
      0
      down vote













      Drawing an image on a canvas is a synchronous operation, what is not, is to load these images.



      So split your logic in 1.Loading, then 2.Drawing



      The loading part will just create as many <img> elements as you need to be drawn, operation greatly cleaned up thanks to Promises.



      Once that's done, the drawing part will just iterate over the images and draw them:






      const ctx = canvas.getContext('2d');

      function loadImages(urls)
      return Promise.all(urls.map(loadImage));


      function loadImage(url)
      return new Promise((res, rej) => Object.assign((new Image()),
      src: url,
      onload: function(e)res(this),
      onerror: rej
      ));


      function drawImages(images)
      images.forEach((img, i) => ctx.drawImage(img, i * 50, 0));


      async function begin() 
      // build up our array of urls
      const urls = Array.from(
      length: 10
      , () => 'https://lorempixel.com/50/50?' + Math.random());
      // load them all
      const images = await loadImages(urls);
      // draw them all
      drawImages(images);


      begin().catch(console.error)

      <canvas id="canvas" width="500" height="50"></canvas>





      Note that it is the basic operations when external assets are required:



      • Load all required assets.

      • Then start using them.





      share|improve this answer






















        up vote
        0
        down vote










        up vote
        0
        down vote









        Drawing an image on a canvas is a synchronous operation, what is not, is to load these images.



        So split your logic in 1.Loading, then 2.Drawing



        The loading part will just create as many <img> elements as you need to be drawn, operation greatly cleaned up thanks to Promises.



        Once that's done, the drawing part will just iterate over the images and draw them:






        const ctx = canvas.getContext('2d');

        function loadImages(urls)
        return Promise.all(urls.map(loadImage));


        function loadImage(url)
        return new Promise((res, rej) => Object.assign((new Image()),
        src: url,
        onload: function(e)res(this),
        onerror: rej
        ));


        function drawImages(images)
        images.forEach((img, i) => ctx.drawImage(img, i * 50, 0));


        async function begin() 
        // build up our array of urls
        const urls = Array.from(
        length: 10
        , () => 'https://lorempixel.com/50/50?' + Math.random());
        // load them all
        const images = await loadImages(urls);
        // draw them all
        drawImages(images);


        begin().catch(console.error)

        <canvas id="canvas" width="500" height="50"></canvas>





        Note that it is the basic operations when external assets are required:



        • Load all required assets.

        • Then start using them.





        share|improve this answer












        Drawing an image on a canvas is a synchronous operation, what is not, is to load these images.



        So split your logic in 1.Loading, then 2.Drawing



        The loading part will just create as many <img> elements as you need to be drawn, operation greatly cleaned up thanks to Promises.



        Once that's done, the drawing part will just iterate over the images and draw them:






        const ctx = canvas.getContext('2d');

        function loadImages(urls)
        return Promise.all(urls.map(loadImage));


        function loadImage(url)
        return new Promise((res, rej) => Object.assign((new Image()),
        src: url,
        onload: function(e)res(this),
        onerror: rej
        ));


        function drawImages(images)
        images.forEach((img, i) => ctx.drawImage(img, i * 50, 0));


        async function begin() 
        // build up our array of urls
        const urls = Array.from(
        length: 10
        , () => 'https://lorempixel.com/50/50?' + Math.random());
        // load them all
        const images = await loadImages(urls);
        // draw them all
        drawImages(images);


        begin().catch(console.error)

        <canvas id="canvas" width="500" height="50"></canvas>





        Note that it is the basic operations when external assets are required:



        • Load all required assets.

        • Then start using them.





        const ctx = canvas.getContext('2d');

        function loadImages(urls)
        return Promise.all(urls.map(loadImage));


        function loadImage(url)
        return new Promise((res, rej) => Object.assign((new Image()),
        src: url,
        onload: function(e)res(this),
        onerror: rej
        ));


        function drawImages(images)
        images.forEach((img, i) => ctx.drawImage(img, i * 50, 0));


        async function begin() 
        // build up our array of urls
        const urls = Array.from(
        length: 10
        , () => 'https://lorempixel.com/50/50?' + Math.random());
        // load them all
        const images = await loadImages(urls);
        // draw them all
        drawImages(images);


        begin().catch(console.error)

        <canvas id="canvas" width="500" height="50"></canvas>





        const ctx = canvas.getContext('2d');

        function loadImages(urls)
        return Promise.all(urls.map(loadImage));


        function loadImage(url)
        return new Promise((res, rej) => Object.assign((new Image()),
        src: url,
        onload: function(e)res(this),
        onerror: rej
        ));


        function drawImages(images)
        images.forEach((img, i) => ctx.drawImage(img, i * 50, 0));


        async function begin() 
        // build up our array of urls
        const urls = Array.from(
        length: 10
        , () => 'https://lorempixel.com/50/50?' + Math.random());
        // load them all
        const images = await loadImages(urls);
        // draw them all
        drawImages(images);


        begin().catch(console.error)

        <canvas id="canvas" width="500" height="50"></canvas>






        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 10 at 6:34









        Kaiido

        37.7k45597




        37.7k45597



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53235858%2fhow-do-i-make-sure-that-images-load-in-the-right-order-on-the-canvas%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            How to how show current date and time by default on contact form 7 in WordPress without taking input from user in datetimepicker

            Syphilis

            Darth Vader #20