Adam
Adam

Reputation: 9049

preloading images in html5/javascript

I've seen example of preloading using multiple images, however I dont know how to apply them to my situation where I only have one image and I'm swapping out frames using the src.

I have a sprite animation that I'm doing, but since there so many images I want to use, I'll have to load them before beginning.

I know the onload fires every time the src is switched and loaded.

How do I preload the images before running the timer? If I'm using "img" onload to preload, do I have to use another Image object to actually display?

<script type="text/javascript">
function init(){
    var numLabel;
    var imgNumber = 1;
    var lastImgNumber = 668;
    var canvas = document.getElementById("mycanvas");
    var context = canvas.getContext("2d");
    var img = new Image;

    img.onload = function(){
        context.clearRect(0,0,context.canvas.width,context.canvas.height);
        context.drawImage(img,0,0);
    };
    var timer = setInterval(function(){
        if(imgNumber>lastImgNumber){
        clearInterval(timer);
        }else{
        numLabel = padNum(imgNumber++,5);
        img.src = "sprite images/opt/movie"+numLabel+".jpg";
        }
    }, 1000/24);
}
function padNum(num, digits){ 
    var str = num + ""; 
    return num.length >= digits? str: padNum("0" + str, digits);
}
</script>

Edit:

I ended up with the following code. However, I think I'm going to check out that sprite sheet method mentioned below.

I basically trying to do full screen video with short clips because I've been reading video in html5 still has its problems with full screen. Also, I think I can get better quality.

<script type="text/javascript">
        var imageArray = new Array();
        var loadedImages = new Array();

        function init(){

            buildImageArray(); //Execute the function to create the array of images
            var total = imageArray.length;
            var count = 0;



            // loop through the images and load.
            while(count < total) {
                loadImage("sprite images/opt/" + imageArray[count],count);


                count++;
            }


        }


        function padNum(num, digits){ 
            var str = num + ""; 
            return num.length >= digits? str: padNum("0" + str, digits);
        }

        function buildImageArray(){
            var firstImage = 1;
            var lastImgNumber = 668;
            var numLabel;


            for(var i = firstImage; i<lastImgNumber+1;i++){
                numLabel = padNum(i,5);
                imageArray.push("movie"+numLabel+".jpg");
            }
        }


        function loadImage(imageSrc,position) {
        // actual function that loads image into DOM

        var image = new Image(); // local scope, new object created per instance.
        image.onload = function() {
            if (!image) return;

            loadedImages[position] = image.src; // record this image path as loaded in global scope
            // or... store the objects themselves so you can inject them:
            // loadedImages.push(this);

            // sample report of progress
            reportProgress();

            // remove event and self to prevent IE on animated gif loops and clear up garbage.
            image = image.onload = image.onabort = image.onerror = null;
        };

        image.src = imageSrc;
        }


         function reportProgress() {
        // used to show how many images loaded thus far and / or trigger some event you can use when done.

        // optional to show onscreen..., 'where' should be an object referencing an element in the DOM
        // to do it silently, just remove the output bits below.
        var output = "loaded ";
        output += loadedImages.length;
        output += " of ";
        output += imageArray.length;
        output += " images.";
        $("#loader").html(output);

            // this bit will fire when all images done:
            if (imageArray.length == loadedImages.length) {
                // total images onComplete. done. rewrite as you deem fit - call your main site load function from here

                // keep in mind that if 1 of your images is a 404, this function may not fire, you
                // may want to assign onerror and onabort events

                //fire beginAnimation
                beginAnimation();
            }
        }


        function beginAnimation(){
            var canvas = document.getElementById("mycanvas");
            var context = canvas.getContext("2d");
            var img = new Image;
            var imgNumber = 0;
            var lastImgNumber = 667;


            img.onload = function(){
                context.clearRect(0,0,context.canvas.width,context.canvas.height);
                context.drawImage(img,0,0);


            };
            var timer = setInterval(function(){
                if(imgNumber>lastImgNumber){

                    clearInterval(timer);

                }else{

                    img.src = loadedImages[imgNumber];
                }
                imgNumber++;


            }, 1000/20);

        }

    </script>

Upvotes: 1

Views: 11239

Answers (2)

Vasiliy Mazhekin
Vasiliy Mazhekin

Reputation: 688

here is an html5 example how load several images using knockoutjs https://github.com/mazhekin/HTML5MultiLoadImages

Upvotes: 0

Simon Sarris
Simon Sarris

Reputation: 63812

This is not the way to go about this.

If the number was smaller I'd offer a second solution but if you seriously have 668 images you need to cut waaaay down. You don't want every user (and your server) making 668 requests and you certainly don't want one IMG thats constantly swapping out the src either.

You need to make a sprite sheet. A single image that looks like this.

Use something like texturepacker to make your single-image sprite sheet: http://www.texturepacker.com/

When it comes time to draw onto the canvas you will need an array that has the x,y,width,height coordinates of each possible sprite in the larger image.

Instead of doing drawImage(img, x, y) you will use the canvas method drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh).

This lets you specify the source rectangle, which will be different for each image. Specifically those arguments correspond to this:

enter image description here

Upvotes: 12

Related Questions