HTML5 Animation

Hi,

I am currently trying to get an animation I made in After Effects working using HTML5, I’m using sprite sheets and with easeljs, but performance seems terrible. It needs to work on iPad.

The dimensions of the web banner animation is 1020 x 411 with around 840 frames and currently I am using this code.


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=0.5, user-scalable=no"/>
<title>EaselJS Sprites Test</title>

<!-- Import EaselJS Framework -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script src="./js/easeljs-0.5.0.min.js"></script>
<script src="js/requestAnimationFrame.js"></script>
<script>

var canvas;
var stage;
var screen_width;
var screen_height;
var bmpAnimation;

var CloudLeft = new Image();
//var CloudLeft2 = new Image();
var CloudRight = new Image();
var iPhoneWheels = new Image();
var conversation = new Image();
var seo = new Image();
var iphoneScreen = new Image();
var hammer = new Image();
var thumb = new Image();

function init() {
    canvas = document.getElementById("testCanvas");

    CloudLeft.onload = handleImageLoad;
    CloudLeft.onerror = handleImageError;
    CloudLeft.src = "sprites/cloudLeft.png";

    /*CloudLeft2.onload = handleImageLoad;
    CloudLeft2.onerror = handleImageError;
    CloudLeft2.src = "sprites/CloudLeft2.png";*/

    CloudRight.onload = handleImageLoad;
    CloudRight.onerror = handleImageError;
    CloudRight.src = "sprites/CloudRight1.png";

    iPhoneWheels.onload = handleImageLoad;
    iPhoneWheels.onerror = handleImageError;
    iPhoneWheels.src = "sprites/iPhoneWheels.png";

    conversation.onload = handleImageLoad;
    conversation.onerror = handleImageError;
    conversation.src = "sprites/conversation.png";

    seo.onload = handleImageLoad;
    seo.onerror = handleImageError;
    seo.src = "sprites/seo.png";

    iphoneScreen.onload = handleImageLoad;
    iphoneScreen.onerror = handleImageError;
    iphoneScreen.src = "sprites/iPhoneScreen.png";

    hammer.onload = handleImageLoad;
    hammer.onerror = handleImageError;
    hammer.src = "sprites/hammer.png";

    thumb.onload = handleImageLoad;
    thumb.onerror = handleImageError;
    thumb.src = "sprites/thumb.png";

}

function reset() {
    stage.removeAllChildren();
    createjs.Ticker.removeAllListeners();
    stage.update();
}

function handleImageLoad(e) {
    startGame();
}


function startGame() {
    // create a new stage and point it at our canvas:
    stage = new createjs.Stage(canvas);
    
    // grab canvas width and height for later calculations:
    screen_width = canvas.width;
    screen_height = canvas.height;
    
    // create spritesheet and assign the associated data.
    var spriteSheet = new createjs.SpriteSheet({
        // image to use
        images: [CloudLeft], 
        // width, height & registration point of each sprite
        frames: {width: 312, height: 92, regX: -110, regY: 30}, 
        animations: {   
            CloudLeftAnim: [0, 120, "CloudLeftAnim"]
        }
    });

    var spriteSheet2 = new createjs.SpriteSheet({
        // image to use
        images: [CloudRight], 
        // width, height & registration point of each sprite
        frames: {width: 252, height: 102, regX: -580, regY: -100}, 
        animations: {   
            CloudRightAnim: [0, 120, "CloudRightAnim"]
        }
    });

    var spriteSheet3 = new createjs.SpriteSheet({
        // image to use
        images: [iPhoneWheels], 
        // width, height & registration point of each sprite
        frames: {width: 42, height: 31, regX: -163, regY: -340}, 
        animations: {   
            iPhoneWheelsAnim: [0, 89, "iPhoneWheelsAnim"]
        }
    });

    var spriteSheet4 = new createjs.SpriteSheet({
        // image to use
        images: [conversation], 
        // width, height & registration point of each sprite
        frames: {width: 46, height: 139, regX: -805, regY: -216}, 
        animations: {   
            conversationAnim: [0, 600, "conversationAnim"]
        }
    });

    var spriteSheet5 = new createjs.SpriteSheet({
        // image to use
        images: [seo], 
        // width, height & registration point of each sprite
        frames: {width: 88, height: 30, regX: -570, regY: -190}, 
        animations: {   
            seoAnim: [0, 825, "seoAnim"]
        }
    });

    var spriteSheet6 = new createjs.SpriteSheet({
        // image to use
        images: [iphoneScreen], 
        // width, height & registration point of each sprite
        frames: {width: 74, height: 59, regX: -30, regY: -330}, 
        animations: {   
            iphoneScreenAnim: [0, 232, "iphoneScreenAnim"]
        }
    });

    var spriteSheet7 = new createjs.SpriteSheet({
        // image to use
        images: [hammer], 
        // width, height & registration point of each sprite
        frames: {width: 36, height: 50, regX: -770, regY: -310}, 
        animations: {   
            hammerAnim: [0, 23, "hammerAnim"]
        }
    });

    var spriteSheet8 = new createjs.SpriteSheet({
        // image to use
        images: [thumb], 
        // width, height & registration point of each sprite
        frames: {width: 326, height: 137, regX: -368, regY: -275}, 
        animations: {   
            thumbAnim: [0, 30, "thumbAnim"]
        }
    });

    // create a BitmapAnimation instance to display and play back the sprite sheet:
    bmpAnimation = new createjs.BitmapAnimation(spriteSheet);
    bmpAnimation2 = new createjs.BitmapAnimation(spriteSheet2);
    bmpAnimation3 = new createjs.BitmapAnimation(spriteSheet3);
    bmpAnimation4 = new createjs.BitmapAnimation(spriteSheet4);
    bmpAnimation5 = new createjs.BitmapAnimation(spriteSheet5);
    bmpAnimation6 = new createjs.BitmapAnimation(spriteSheet6);
    bmpAnimation7 = new createjs.BitmapAnimation(spriteSheet7);
    bmpAnimation8 = new createjs.BitmapAnimation(spriteSheet8);


    // start playing the first sequence:
    bmpAnimation.gotoAndPlay("CloudLeftAnim");   //animate
    bmpAnimation2.gotoAndPlay("CloudRightAnim");
    bmpAnimation3.gotoAndPlay("iPhoneWheelsAnim");
    bmpAnimation4.gotoAndPlay("conversationAnim");
    bmpAnimation5.gotoAndPlay("seoAnim");
    bmpAnimation6.gotoAndPlay("iphoneScreenAnim");
    bmpAnimation7.gotoAndPlay("hammerAnim");
    bmpAnimation8.gotoAndPlay("thumbAnim");

    bmpAnimation.name = "cloud1";
    bmpAnimation.direction = 90;
    bmpAnimation.vX = 0.5;
    bmpAnimation.x = 16;
    bmpAnimation.y = 32;

    bmpAnimation2.name = "cloud2";
    bmpAnimation2.direction = 90;
    bmpAnimation2.vX = 0.5;
    bmpAnimation2.x = 16;
    bmpAnimation2.y = 32;
    
    // have each monster start at a specific frame
    bmpAnimation.currentFrame = 0;
    stage.addChild(bmpAnimation);

    bmpAnimation2.currentFrame = 0;
    stage.addChild(bmpAnimation2);

    bmpAnimation3.currentFrame = 0;
    stage.addChild(bmpAnimation3);

    bmpAnimation4.currentFrame = 0;
    stage.addChild(bmpAnimation4);

    bmpAnimation5.currentFrame = 0;
    stage.addChild(bmpAnimation5);

    bmpAnimation6.currentFrame = 0;
    stage.addChild(bmpAnimation6);

    bmpAnimation7.currentFrame = 0;
    stage.addChild(bmpAnimation7);

    bmpAnimation8.currentFrame = 0;
    stage.addChild(bmpAnimation8);

    // we want to do some work before we update the canvas,
    // otherwise we could use Ticker.addListener(stage);
    createjs.Ticker.addListener(window);
    createjs.Ticker.useRAF = true;
    createjs.Ticker.setFPS(24);
}

//called if there is an error loading the image (usually due to a 404)
function handleImageError(e) {
    console.log("Error Loading Image : " + e.target.src);
}

function tick() {

        // Hit testing the screen width, otherwise our sprite would disappear
    if (bmpAnimation.y >= screen_height - 370) {
        // We've reached the right side of our screen
        // We need to walk left now to go back to our initial position
        bmpAnimation.direction = -90;
    }

    if (bmpAnimation.y < 16) {
        // We've reached the left side of our screen
        // We need to walk right now
        bmpAnimation.direction = 90;
    }

    // Moving the sprite based on the direction & the speed
    if (bmpAnimation.direction == 90) {
        bmpAnimation.y += bmpAnimation.vX;
    }
    else {
        bmpAnimation.y -= bmpAnimation.vX;
    }

        // Hit testing the screen width, otherwise our sprite would disappear
    if (bmpAnimation2.y >= screen_height - 370) {
        // We've reached the right side of our screen
        // We need to walk left now to go back to our initial position
        bmpAnimation2.direction = -90;
    }

    if (bmpAnimation2.y < 16) {
        // We've reached the left side of our screen
        // We need to walk right now
        bmpAnimation2.direction = 90;
    }

    // Moving the sprite based on the direction & the speed
    if (bmpAnimation2.direction == 90) {
        bmpAnimation2.y += bmpAnimation2.vX;
    }
    else {
        bmpAnimation2.y -= bmpAnimation2.vX;
    }



    // update the stage:
    stage.update();

}

</script>
<style type="text/css"></style></head>
    
<body onload="init();">
    <div class="description">

    </div>
    <div class="canvasHolder">
           <canvas id="testCanvas" width="1020" height="411" style="background-image:url('background.png')">
            Your browser doesn't support canvas. Please download IE9+ on <a href="http://ie.microsoft.com/testdrive">IE Test Drive</a> 
        </canvas>
    </div>


</body></html>


Is there a better way to use HTML5 for animations or are sprite sheets the only way forward? I’ve tried an image sequence but their are too many http requests and the page takes an age to load.

Thanks for any input
Simon