2

I've created an intro animation to a page I'm working on using jQuery and Raphael, a javascript library. The animation works the way I'd like it to, but is oftentimes jumpy. Usually refreshing will cause it to animate much smoother than on its first page load. I'm wondering if this has anything to do with load times or if it's just the efficiency of my code.

You can see the page at: http://developer.crawford.com as well as the animation code below.

Is there any way to increase efficiency when it comes to javascript animations, or specifically with my code? Am I doing anything to cause the script to be very inefficient? Is there any good way to give the code a few seconds to load before executing to maybe make it run smoother other than simply setTimeout()?

function introAnimation() {
// creating the canvas
var paper = new Raphael(document.getElementById('mainCanvas'), '100%', '100%');

var canvasWidth = 500;
var canvasHeight = 500;
var offset = .6;
// speed of circle getting bigger
var speed1 = 1000;
// speed of circles diverging
var speed2 = 1200;
var hide = Raphael.animation({'opacity': 0});

// ellipse variable instantiation
var cRadius = 105;
var diam = cRadius*2;
// centerpoint
var cX = canvasWidth/2;
var cY = canvasHeight/2;

var circ1 = paper.ellipse(cX, cY, 10, 10);
circ1.attr({opacity: 1, stroke: '#777'});

var circRed = paper.ellipse(cX, cY, cRadius, cRadius).attr({opacity: 0, stroke: '#777'});
var circGreen = paper.ellipse(cX, cY, cRadius, cRadius).attr({opacity: 0, stroke: '#777'});
var circBlue = paper.ellipse(cX, cY, cRadius, cRadius).attr({opacity: 0, stroke: '#777'});  

//red, green, blue watermarks, and logo
var redWatermark = paper.image('images/circle_red.png', cX-50, cY-50, 100, 100).attr({opacity: 0});
var greenWatermark = paper.image('images/circle_green.png', cX-50, cY, 100, 100).attr({opacity: 0});
var blueWatermark = paper.image('images/circle_blue.png', cX-50, cY, 100, 100).attr({opacity: 0});

var logoWidth = 60;
var logoHeight = 30;
var logo = paper.image('images/CMS_logo_only.png', cX-(logoWidth/2), cY*1.04, logoWidth*.95, logoHeight*.95).attr({opacity: 0});

var letterOffset = cRadius*1.2;
// circle centerpoints xR, yR: center of red; xG, yG: center of green; xB, yB: center of blue
var xR = cX; var yR = cY-cRadius*offset;
var xG = cX-cRadius*offset; var yG = cY+cRadius*offset;
var xB = cX+cRadius*offset; var yB = cY+cRadius*offset;

// insert CMS letter text
var c = paper.text(xR-Math.cos(.8)*letterOffset, yR-Math.sin(.8)*letterOffset, "c.").attr({fill: '#737373', 'font-size': '25px', 'font-family': 'IMFELLDWPicaItalic', opacity: 0});
var m = paper.text(xG+Math.cos(5*Math.PI/4)*letterOffset, yG-Math.sin(5*Math.PI/4)*letterOffset, "m.").attr({fill: '#737373', 'font-size': '25px', 'font-family': 'IMFELLDWPicaItalic', opacity: 0});
var s = paper.text(xB+Math.cos(0)*letterOffset, yB-Math.sin(0)*letterOffset, "s.").attr({fill: '#737373', 'font-size': '25px', 'font-family': 'IMFELLDWPicaItalic', opacity: 0});

// white overlap
// Three points of overlap:
var pointTopX = cX; var pointTopY  = cY-(cRadius*.2);
var pointLeftX = cX-(cRadius*.365); var pointLeftY = cY+(cRadius*.33);
var pointRightX = cX+(cRadius*.365); var pointRightY = cY+(cRadius*.33);
var pathString = 'M'+pointTopX+' '+pointTopY+'A'+cRadius+' '+cRadius+' '+xG+' '+yG;
var pathString =    "M"+pointTopX+" "+pointTopY+','
                    +"A"+cRadius+","+cRadius+",0,0,0,"+pointLeftX+","+pointLeftY+','
                    +"A"+cRadius+","+cRadius+",0,0,0,"+pointRightX+","+pointRightY+','
                    +"A"+cRadius+","+cRadius+",0,0,0,"+pointTopX+","+pointTopY;
var overlapFill = paper.path(pathString).attr({'stroke-width': 0, fill: '#fff', opacity: 0});
var overlapPath = paper.path(pathString).attr({opacity: 0});

//resize circle
circ1.animate({ 'rx': cRadius, 'ry': cRadius }, speed1, function() {
    //hide it once it's done
    circ1.animate({opacity: 0}, 0);
    //show other circles
    circRed.animate({opacity: 1}, 0);
    circGreen.animate({opacity: 1}, 0);
    circBlue.animate({opacity: 1}, 0);
    //move other circles
    circRed.animate({cy: cY-cRadius*offset, rx: cRadius, ry: cRadius}, speed2);
    circGreen.animate({cx: cX-cRadius*offset, cy: cY+cRadius*offset, rx: cRadius, ry: cRadius}, speed2);
    circBlue.animate({cx: cX+cRadius*offset, cy: cY+cRadius*offset, rx: cRadius, ry: cRadius}, speed2);

    logo.animate({opacity: 1}, speed2);

    //move to center
    redWatermark.attr({width: diam, height: diam, x: imgX(cX, diam), y: imgY(cY, diam)});
    greenWatermark.attr({width: diam, height: diam, x: imgX(cX, diam), y: imgY(cY, diam)});
    blueWatermark.attr({width: diam, height: diam, x: imgX(cX, diam), y: imgY(cY, diam)});
    //animate out
    redWatermark.animate({y: imgY(cY-cRadius*offset, diam), opacity: .35}, speed2);
    greenWatermark.animate({x: imgX(cX-cRadius*offset, diam), y: imgY(cY+cRadius*offset, diam), opacity: .35}, speed2);
    blueWatermark.animate({x: imgX(cX+cRadius*offset, diam), y: imgY(cY+cRadius*offset, diam), opacity: .35}, speed2, function() {
        logo.toFront();
        c.animate({opacity: 1}, 1000); m.animate({opacity: 1}, 1000); s.animate({opacity: 1}, 1000);
        overlapFill.animate({opacity: 1}, 1000); overlapPath.animate({opacity: .3}, 1000);
        //nav slide in
        nav();
    });
});

redWatermark.hover(function() {
    $('#createSub').slideDown(300);
});
redWatermark.mouseout(function() {
    $('#createSub').slideUp(300);
});
greenWatermark.hover(function() {
    $('#storeSub').slideDown('fast');
});
greenWatermark.mouseout(function() {
    $('#storeSub').slideUp('fast');
});
blueWatermark.hover(function() {
    $('#manageSub').slideDown('fast');
});
blueWatermark.mouseout(function() {
    $('#manageSub').slideUp('fast');
});

}

1
  • use flash! just kidding. Commented Jan 24, 2012 at 20:57

3 Answers 3

6

Your PNG's are 400+k http://developer.crawford.com/images/circle_blue.png

You're forcing users to download over a meg of image data while trying to animate it at the same time. This will not be smooth for most visitors. I'd recommend either compressing/shrinking your images, or preloading them.

Sign up to request clarification or add additional context in comments.

2 Comments

Seconded; use lower resolution images. Also perhaps try a stand-in graphic to have something to show while the other images load.
Great suggestion. I think that sometimes the most obvious are easily overlooked. I got them down to 30Kb each without any loss of quality. Here's a good compression script that doesn't result in quality loss for anyone else who has this problem: punypng.com
1

Replace repeated calculations with the result:

Variations of cY-cRadius*offset appears often, so calculate it ahead of time.

3 Comments

I'm sure that's because the offset is consistently changing throughout the animation.
Good idea. I actually have the offset so that everything is set in terms of ratios so I can easily edit the size of the animation. Between this and the other suggestion, I was able to make it much smoother.
Nice-looking site. Your left menu does a bit of a yo-yo effect at the moment though. look into using .stop()
0

It looks jumpy to me too. Have you considered pre-caching your images before you call any of the animation?

1 Comment

That's kind of what I was getting at. My question is what is a way that I can do this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.