Forums

The forums ran from 2008-2020 and are now closed and viewable here as an archive.

Home Forums JavaScript Can I sync up multiple image onload calls?

  • This topic is empty.
Viewing 7 posts - 1 through 7 (of 7 total)
  • Author
    Posts
  • #35881
    noahgelman
    Participant

    I want a function to run when specific images are loaded, but I don’t know how to wait for both to load before running. I only know how to chain them, like below:

    Image1 = new Image();
    Image1.src = 'image1-link.jpg';

    Image2 = new Image();
    Image2.src = 'image2-link.jpg';

    Image1.onload = function() {
    Image2.onload = function() { ... }
    }

    The downside to this is it has to wait till Image1 completely loads before getting the second. I want to try something like this:

    Image1 = new Image();
    Image1.src = 'image1-link.jpg';

    Image2 = new Image();
    Image2.src = 'image2-link.jpg';

    (Image1 && Image2).onload = function() { ... }

    How can I do this?

    #93673
    Mottie
    Member

    Hi Noah!

    Actually recently blogged a snippet of code/mini plugin that basically does this.

    Here is the code:

    /*
    Check if all images are loaded
    - Callback occurs when all images are loaded
    - image load errors are ignored (complete will be true)
    - Use:
    $('.wrap img').imagesLoaded(function(){
    alert('all images loaded');
    });
    */

    jQuery.fn.extend({
    imagesLoaded: function( callback ) {
    var i, c = true, t = this, l = t.length;
    for ( i = 0; i < l; i++ ) {
    if (this.tagName === "IMG") {
    c = (c && this
    .complete && this.height !== 0);
    }
    }
    if (c) {
    if (typeof callback === "function") { callback(); }
    } else {
    setTimeout(function(){
    jQuery(t).imagesLoaded( callback );
    }, 200);
    }
    }
    });

    If you use $(window).load(){ /* code here */ }); then you already know all images are loaded. But if you lazy load or add more images after the page has loaded, this is an alternative method.

    Here is how to use it to run the callback after multiple images have finished loading:

    $(function(){
    $('.wrap img').imagesLoaded(function(){
    alert('all images loaded');
    });
    });

    Or, if you only have one image, just target that image

    $('img#fred').imagesLoaded(function(){
    alert('Fred!');
    });

    If there are no images in your selector, it automatically runs the callback by default.

    #93677
    noahgelman
    Participant

    @mottie

    Thanks, but not quite what I needed. I should have been more specific. These images aren’t been loaded into tags, I’m using them in an HTML5 canvas. The user is able to change what’s drawn on the canvas via buttons and I want to make sure the images related to that are all loaded up before running all my other code.

    #93678
    Mottie
    Member

    It should be the same basic idea… I’m still learning canvas, but it still needs to load images before it can render them, right?

    #93679
    noahgelman
    Participant

    Yes, it has to load the image first to use its data to draw on the canvas.

    #93731
    noahgelman
    Participant

    Here are 2 answers via stack overflow:

    // loader will 'load' items by calling thingToDo for each item,
    // before calling allDone when all the things to do have been done.
    function loader(items, thingToDo, allDone) {
    if (!items) {
    // nothing to do.
    return;
    }

    if ("undefined" === items.length) {
    // convert single item to array.
    items = [items];
    }

    var count = items.length;

    // this callback counts down the things to do.
    var thingToDoCompleted = function (items, i) {
    count--;
    if (0 == count) {
    allDone(items);
    }
    };

    for (var i = 0; i < items.length; i++) {
    // 'do' each thing, and await callback.
    thingToDo(items, i, thingToDoCompleted);
    }
    }

    function loadImage(items, i, onComplete) {
    var onLoad = function (e) {
    e.target.removeEventListener("load", onLoad);

    // this next line can be removed.
    // only here to prove the image was loaded.
    document.body.appendChild(e.target);

    // notify that we're done.
    onComplete(items, i);
    }
    var img = new Image();
    img.addEventListener("load", onLoad, false);
    img.src = items;
    }

    var items = ['http://bits.wikimedia.org/images/wikimedia-button.png',
    'http://bits.wikimedia.org/skins-1.18/common/images/poweredby_mediawiki_88x31.png',
    'http://upload.wikimedia.org/wikipedia/en/thumb/4/4a/Commons-logo.svg/30px-Commons-logo.svg.png',
    'http://upload.wikimedia.org/wikipedia/commons/3/38/Icons_example.png'];

    loader(items, loadImage, function () {
    alert("done");
    });

    and here is a jsFiddle link for you http://jsfiddle.net/8baGb/1/
    Second solution:

    var imageCollector = function(expectedCount, completeFn){
    var receivedCount;
    return function(){
    if(++receivedCount == expectedcount){
    completeFn();
    }
    };
    }();

    var ic = imageCollector(2, function(){alert("Done!");});
    Image1.onload = ic;
    Image2.onload = ic;

    And here is a link to the Stack Overflow thread

    #181778
    julmot
    Participant

    I had the same problem like you. I wanted to wait for multiple callbacks. Because I did not found any plugin I built a plugin for that. You can define a stack of images and on which element you want them to be appended. Your callback function will be called after all elements are successfully added to the defined element and are all loaded. You can use the same for JavaScripts.

    Usage:

    
          var requireFile = new jm.RequireFile();
          requireFile.addStackToDOM({
              // The stack with the images to load
              'stack': [
                  'exampleFiles/image.png'
               ],
               // The selector where the image should appear,
               // if non is defined it will be appended to the <body>-element
               'insertInto': '#load-images-here',
               // The callback if all scripts are loaded
              'completed': function(){
                  alert('Hey all my images are loaded');
              }
          });
    

    Documentation and Download

Viewing 7 posts - 1 through 7 (of 7 total)
  • The forum ‘JavaScript’ is closed to new topics and replies.