Search code examples
htmlcachingonloadeaseljs

HTML5 images loading improperly on first load even with image.onload


Alright so I'm working on a webapp using EaselJS and on first load after I clear my cache, my images are loading in the top left at default size (basically x:0,y:0,scale:1) instead of what I specify . I get that this is a async image loading error but I used image.onload to call the function that does all the actual drawing, and this doesn't seem to affect anything at all.

Here is the relevant code. I also made a fiddle that shows the caching problem, but the actual functionality of the app doesn't work because of cross domain images. https://jsfiddle.net/a9m66tcL/2/

    function initToolbar(stage){
      let toolbarImages = [];
      let toolbar = new createjs.Shape();
      toolbar.graphics.beginFill("black");
      toolbar.graphics.drawRect(0, 580, 960, 120);
      toolbarContainer.addChild(toolbar);

      // load the source images:
      for (name of imageManifest){
        let image = new Image();
        image.src = "SacredSpace/"+ name +".png";
        image.onload = loadToolbarImage(toolbarImages, image);
      }
      stage.addChild(toolbarContainer);
    }

    function loadToolbarImage(toolbarImages, image) {
      toolbarImages.push(image);
      let bitmap = new createjs.Bitmap(image);
      toolbarContainer.addChild(bitmap);
      bitmap.x = toolbarImages.length * 150 + 100;
      bitmap.y = 640;
      bitmap.regX = bitmap.image.width / 2 | 0;
      bitmap.regY = bitmap.image.height / 2 | 0;
      if (image.width > image.height){
        bitmap.scaleX = bitmap.scaleY = 100/ image.width
      }else{
        bitmap.scaleX = bitmap.scaleY = 100/ image.height
      }
      bitmap.on("mousedown", function (evt) {
        addObject(image)
        update = true;
      });
    }

Solution

  • This is incorrect:

    image.onload = loadToolbarImage(toolbarImages, image);
    

    Instead of firing onload, it is being called immediately, and the result is returned as the onload handler. The correct syntax is:

    image.onload = loadToolbarImage; // Pass the function by reference
    

    Since it looks like you are using ES6, use:

    image.onload = e => loadToolbarImage(toolbarImages, e);
    

    To pass parameters along in ES5, you can do something like this:

    image.onload = loadToolbarImage.bind(this, toolbarImages, image);
    

    I would further recommend moving the toolbarImages outside of your init function so it is accessible, and using the event target for the image. That way you aren't trying to propagate the image and array manually.

    Cheers,