javascripthtml5-canvascreatejspreloadjs

createjs flash cc, separate manifest preloading


I’ve an animation based html project built on Flash CC and struggling about preloading separately.

What I am trying to do is;

  1. Load 1 image (says “please wait”) and createjs export.
  2. Animation stops at the begining of timeline, call a function here.
  3. load some assets.
  4. start animation
  5. stop animation at a certain point on timeline. Then load assests of next part of animation.
  6. When loading complete, continue on animation. etc.

I’m ok with loading all assets and playing the whole animation. But when it comes to separate the manifests; it loads the files I wanted and continues to the animation, but loaded images are not displaying on canvas.

I’m using the below code as init.js file in html;

var canvas, stage, exportRoot;

function init() {
    canvas = document.getElementById("canvas");
    images = images||{};
    preloadLaunch(); 
}

function preloadLaunch(){
    var loader = new createjs.LoadQueue(false);
    loader.addEventListener("fileload", handleFileLoad);
    loader.addEventListener("complete", handleComplete);
    loader.loadManifest(lib.properties.manifestLaunch); //selects the manifest from createjs export,  first image says please wait.
}


function handleFileLoad(evt) {
    if (evt.item.type == "image") { images[evt.item.id] = evt.result; }
}

function handleComplete() {
    exportRoot = new lib.project();
    stage = new createjs.Stage(canvas);
    stage.addChild(exportRoot);
    stage.update();
    stage.enableMouseOver();
    createjs.Ticker.setFPS(lib.properties.fps);
    createjs.Ticker.addEventListener("tick", stage); 
}


/// triggers from animation timeline
function preloadPart01() {
    var loader01 = new createjs.LoadQueue(false);
    loader01.addEventListener("fileload", handleFileLoad);
    loader01.addEventListener("complete", start);
    loader01.loadManifest(lib.properties.manifestPart01); //selects the manifest from createjs export   
}

function start() {
    stage.update();
    exportRoot.animation.gotoAndPlay("START"); // files are loaded in manifestPart01 and starts the animation, but loaded images are not visible.
}

I was thinking that was about "getResult" but I couldn't implement it to the code. I'll be glad for any help.

Thank you very much.


Solution

  • The reason this won't work is because when you instantiate the exportRoot, it builds all the content in the timeline that the exportRoot will need, including any Bitmap instances. The bitmaps are instantiated using the loaded images that are stored in the global images object, so if you have not yet preloaded their content, they are given a null image - and there is no mechanism to update them when you load the secondary content.

    Here is a snippet from a Bitmap instance in the exported library:

    (lib.BitmapName = function() {
        this.initialize(img.BitmapName); // THIS WILL BE NULL IF LOADED LATER
    }).prototype = p = new cjs.Bitmap();
    p.nominalBounds = new cjs.Rectangle(0,0,600,800);
    

    You should be able to get around this by pre-creating references in the global images object, and updating it later on:

    // Pre-create dummy instances BEFORE you create the `exportRoot`
    var manifest = lib.properites.manifestPart01;
    for (var i=0, l=manifest.length; i<l; i++) {
        images[manifest.id] = document.createElement("img"); // Empty instances
        // Note: Don't set src
    }
    

    Then in the handleFileLoad method, update the instance if it exists.

    function handleFileLoad(evt) {  
        if (evt.item.type == "image") { 
            if (images[evt.item.id] != null) {
                // Just update the existing instance.
                images[evt.item.id].src = evt.result.src;
            } else {
                // Original behaviour
                images[evt.item.id] = evt.result; 
            }
        }   
    }
    

    This should work, because as long as the image instance exists when your library items are created, it will display once the image is loaded. Note that because this sets a src property, there will be a short delay as the image is pulled from the browser cache (usually a full tick).

    Full disclosure -- I didn't test this, but based on what I know about EaselJS, it should work just fine. I am interested in hearing if this works for you.

    One additional note: If you have a Ticker updating the stage, you don't need the extra stage.update() call in your start method (it will just do an extra draw for no reason).