You are reading a MIX Online Opinion. In which we speak our minds. Tim Aidlin Meet Tim Arrow

Lab Notes

14Comment Retweet

Using jQuery to animate a Hero

Aug 12, 2010 In Process By Tim Aidlin

For a long time designers were forced to use Macromedia / Adobe Flash for a lot of animations in their designs. With the rise of JavaScript, however, designer/developers are now empowered to create a vast array of animations and functionality that often used to require plug-ins. Now that the wider community has started to coalesce behind web standards, the use of JavaScript for progressive enhancement of websites has become de rigeur, providing wonderful opportunities for designers and developers to collaborate.

MIX Online’s Glimmer

I started using JavaScript with a bit of hesitation, coming from a background steeped in front-end web design and development, using Flash and then Silverlight for animation and interactivity. I found the JavaScript syntax a little difficult to understand at first. I felt I was lacking ways to visually design interactions with JavaScript.

We found other designers were having this problem too. To fill this need, last year we at MIX Online designed, developed and published Glimmer, which allows designers and developers to create interactive elements and animations on web pages using jQuery. Glimmer also helps you learn how to write good jQuery by allowing you to open your HTML in a program that interacts with your code and generates the correct files.

For help getting started coding your own jQuery, check out this great tutorial by Matt Doyle. http://www.elated.com/articles/super-easy-animated-effects-with-jquery/

Not long ago we released another Lab called The Archivist. We used Glimmer on the home page http://archivist.visitmix.com to add jQuery animations to the main Hero graphic. jQuery allows for some fun animation styles and shows off our new mascot, Friendly Green Robot.

The first section of the following tutorial demonstrates how I set up my HTML and CSS to take advantage of jQuery. The second half of the tutorial focuses on how to use Glimmer to produce that jQuery.

Download the files and dive in directly,or read on …

Watch The Screencast

To help you through the various steps below,I’ve created a short screencast that gives a brief overview of the process detailed in the tutorial. Check it out before you get into the details of building out the application on your own.

width=”320″ height=”240″>
Oomph artwork
You need Silverlight to view this video. It’s fast, it’s free and it’s awesome. Click here to get it.


The File Structure

I almost always set up my file structure at the beginning of each project. I always copy the following from a folder named ‘_base’ when starting:

filestructure

The HTML

To have your Hero banner animate correctly, you’ll need to think about the structure of your HTML and the CSS you’ll use to create it. I generally think of these animations as having ‘slides’ and ‘elements’ within those ‘slides’. In this example, we’re creating a graphic that will have two slides that animate in and out. The first slide consists of two elements. The second consists of three elements.

Below is the HTML I used to create the animated header. It has a very basic structure consisting of:

Main hero container

  • Slide 1
    • Text
    • Big Robot
  • Slide 2
    • Little robot
    • Screen 1
    • Screen 2
<div id="hero">
 <div id="horizontalLine"><img alt="" src="images/robotHero/horizontalLine.png" width="940" height="19" /> </div>
  <div id="slide1">
   <div id="slide1text"><img alt="Start an archive"
   src="images/robotHero/text1.png" width="323" height="100" /> </div>
   <div id="bigGuyPointing"><img alt="The Archivist"
   src="images/robotHero/bigRobot.png" /> </div>
  </div>

  <div id="slide2">
   <div id="slide2text"><img alt="Start an archive"
   src="images/robotHero/text2.png" width="209" height="100" /> </div>
   <div id="standingRobot"><img alt="The Archivist"
   src="images/robotHero/standingRobot.png" /> </div>
   <div id="vis1"></div>
   <div id="vis2"></div>
  </div>
</div>

The CSS There are a few things to note in the CSS that will make the Hero animate correctly. First, ensure that the main container—in this case, #hero—has ‘overflow:hidden’. This will act as a mask that will hide the individual parts of the animation when they flow outside the boundaries of the hero container.

Secondly, all items that you want to animate should have their position set (‘position:absolute’, for example). It doesn’t necessarily matter to jQuery if the position is set to absolute or relative, as long as it’s set.

The third item to note in this example is that the second slide of the animation is set to ‘display:none;’. In the jQuery, we’ll be toggling the visibility of the different slides. We display the first slide by default, which makes for a good experience in the rare case that someone has his or her JavaScript turned off. Those users would just see a static image. We’ll be toggling the visibility of the different panels by using jQuery to modify the CSS ‘display’ function.

#hero{
width:940px;
height:180px;
background-image:url('../images/333background.jpg');
background-repeat:repeat;
overflow:hidden;
position:relative;
}

#horizontalLine{
display:none;
width:940px;
height:19px;
margin-top:150px;
position:absolute;
}

#slide1{
display:block;
}

#slide1text{
width:323px;
height:100px;
position:relative;
margin:40px;
}

#bigGuyPointing{
width:535px;
height:551px;
position:relative;
margin:-200px 0 0 400px;
}

#slide2{
display:none;
}

#slide2text{
width:209px;
height:105px;
position:absolute;
margin:40px 40px 40px 140px;
}

#standingRobot{
width:535px;
height:551px;
position:absolute;
margin:26px 0 0 30px;
}

#vis1{
position:absolute;
width:249px;
height:148px;
background-image:url('../../images/robotHero/line.png');
background-repeat:no-repeat;
margin:32px 20px 20px 380px;
}

#vis2{
position:absolute;
width:249px;
height:148px;
background-image:url('../../images/robotHero/pie.png');
background-repeat:no-repeat;
margin:32px 20px 20px 650px;
}

Glimmer

The next step is to fire up Glimmer and get started on the animation. Let’s go.

Download Glimmer

http://visitmix.com/labs/glimmer/

Glimmer

Getting Started

  1. In the top menu, go to File > Open and find your html hero. Open that file.

Glimmer

  1. Click Add New Action
  2. Click Action Name 1 to expand the field

Glimmer

Step 1: Clear the field

Action Name—This will be the first step of the animation. Here, I’m naming the action ‘clear_canvas’. I want this action to happen directly when the page loads, so under Action Type I choose ‘load’. I leave the Trigger field blank because I want the animation to start without a trigger (say, a mouse-click, or hover-over).

The first Target I want to animate is the text “Start an archive …” I choose ‘#slide1Text’ from the dropdown. In that Target dropdown you should see all the elements of your html page. From here you can choose what you’re animating and what you’re doing to it.

Next I choose the effect I want to have on the text. In this case, I want to move it from the left of the screen to where it currently is. To do this I choose ‘X Position Animation’ from the Add Effects dropdown. Click the checkbox next to Start and in the Start field, enter -600. This means that we want the target—#slide1text—to start 600 pixels to the left of where it currently is. We leave the ‘End’ value at 0 because 0 is where the target originally was, and it’s where we want it to be at the end of this slide.

Underneath the Target dropdown you’ll see Options. Click the toggle and set the Action Duration to 600. This field gives you control over how long the animation takes. In this case, we’re setting the animation to 600 milliseconds. We also have the option to add some effects such as bouncing, easing, swaying, etc. In this case, we’ll add some elasticity to the animation and choose ‘easeOutElastic’. You’ll note you have a few options (such as ‘easeInElastic). The difference here is easeOutElastic makes the elastic happen at the end of the animation, while easeInElastic makes it happen at the beginning.

Glimmer

Let’s Save!

Glimmer

As noted earlier, I like to keep all my files in their own file-type folders. I’m being asked to save JavaScript files, so I choose my js folder for the destination I’d like files written to. Glimmer will automatically save the .js file that’s particular to your site, as well as other .js files that enable effects and functionality.

Saving also inserts references to these JavaScript files into your HTML. Be aware: If you have your HTML open in another program, you should reload it before further editing since Glimmer inserts the references to the JavaScript files into the <head> of your HTML.

<!--Start Glimmer Insertion-->
<script type='text/javascript' src='js/jquery-1.3.2.min.js'></script>
<script type='text/javascript' src='js/effects.core.js'></script>
<!--glimmer generated file-->
<script type='text/javascript' src='js/hero-stage2.html.glimmer.js'></script>
<!--End Glimmer Insertion-->

Back to Step 1

In addition to bringing in the text, we also want to bring in the Big Green Friendly Robot. We want to do this a second or so later than the text. To accomplish this we first remove him from the stage by clicking ‘Add a target’, which spawns a new panel in the clear_canvas action.

Glimmer

We then set ‘#bigGuyPointing’ as the Target and again use X Position Animation. This time, though, we move The Big Green Friendly Robot to the right 600 pixels and leave him there by setting both the Start and End fields to 600.

We also need to ensure that this panel is visible when the animation loop begins again. To do this, we toggle the CSS:

  1. Target: #slide1
  2. Add Effects: Modify CSS Effect
  3. Name: display
  4. Value: block

Step 2: Bring On the Big Green Friendly Robot

Click on Add New Action and name this action ‘big_guy_in’. In this case, we’re going to have the clear_canvas action trigger the big_guy_in action, so we can leave the Action type and Trigger fields empty.

Click Add a target and choose #bigGuyPointing. Under Options, set the time to 600 milliseconds again and choose easeOutElastic. Since the Robot is already off the canvas, all we need to do is bring him in. That means that he should end at 0. Under Add Effects, we’ll choose X Position Animation and leave the End field at 0.

Glimmer

Now we have to trigger the big_guy_in action. We do this by setting a timer on the clear_canvas action. In the clear_canvas action, find the Add Effects dropdown and add the Timer Effect to either of the targets. In the Chained Action field enter big_guy_in and set the duration to 600. This effect will trigger the big_guy_in action in 600 milliseconds (.6 second).

Glimmer

Step 3: Waiting and leaving

Next we’ll build the exit of these pieces by doing what we did above, only backwards. First, choose Add New Action and name it ‘slide1_out’. Again, since this action is going to be triggered by the stage before it, we need not assign an Action Type or Trigger. We do, however, have to assign Targets, which are the text and Robot.

  1. Choose #slide1text from the Target dropdown.
  2. Click the Options panel and set the Action Duration to 600 and Action Easing to easeInBounce.
  3. Choose X Position Animation and set the End field to 600
  4. Save
  5. Click Add a target
  6. Choose #bigGuyPointing from the Target menu
  7. Under Options, set the time to 600 and easing to easeInBounce
  8. Choose X Position Animation from the Add Effects dropdown.
  9. In the End field, type -600
  10. Save
  11. In big_guy_in action, choose Timer Effect from the Add Effects dropdown.
  12. Enter slide1_out in the Chained Action field, and change the duration to 6000 (6 seconds). This will let the slide stay static for 6 seconds; then the two pieces will slide away.

Step 4: Bring in Slide 2

In this step, we’ll basically repeat what we did with the first part of the animation, but this time we’ll have to make the slide visible by changing a CSS setting. We’ll also have the parts of the slide come in vertically and set the opacity on the little Friendly Green Robot.

  1. Choose Add New Action
  2. Expand and name slide2_in
  3. Target: #slide2
  4. Add Effects: Modify CSS Effect
  5. Name: Display
  6. Value: block
  7. Save
  8. Action: slide1out
  9. Add Effects (to either of the existing targets): Timer Effects
  10. Chained Action: slide2_in
  11. Duration 2000

You’ll see that this pops the second slide in, but we want to animate it nicely. We’ll do basically what we did to slide1 with the clear_canvas action. Let’s move the little guy off the stage and bring him on nicely.

  1. In slide2_in, add a new Target of #standingRobot
  2. Add effect: Y Position Animation
  3. Check Start and give that a value of 500. This will push the robot down 500 pixels.
  4. Leave End at 0, which is the endpoint of the animation
  5. Add Effects: Opacity Animation
  6. Check Start and set to 0 (100% transparent)
  7. Set the End value to 1 (100% opacity)
  8. Open the Options panel and set Action Duration to 600 and Action Easing to swing
  9. We still have to get the text and panels off of the stage in order to animate them in during the next phase
  10. Add a new Target: #slide2text
  11. Add effect: Y Position Animation
  12. Check Start and give both the start *and end* a value of -200. Do the same for the panels by choosing #vis1 and #vis2 as new Targets and repeating. If you’d like to have one of the pieces come from the bottom, change the value from -200 to 200.

Okay, now we have just the little standing robot on the second slide. Let’s save and move on to animating the text and panels.

  1. Add New Action
  2. Action Name: slide2_textpanels
  3. Target: #slide2text
  4. Y Position Animation
  5. End value should remain at 0
  6. In the Options panel, set the Action Duration to 600 and the Action Easing to ‘Swing’
  7. Repeat this for the Targets #vis1 and #vis2

We still need to trigger this part of the animation. In the slide2_in action, add the Timer effect to the #slide2 Target. We’ll point the Chained Action to slide2_textpanels and set the duration to 600, which is how long it takes for the little Friendly Green Robot to slide up.

Glimmer

The last thing we need to do is clear off the second slide and go back to slide1. To do this, simply create a final action, move all the pieces off the canvas using Y Position Animation, and set a Timer Effect to trigger the clear canvas action. That will set the loop in motion.

Your final jQuery (.js) file should look like the following, with one exception:

jQuery(function($) {
var timer;
function clear_canvas(event)
{
clearTimeout(timer);
timer = setTimeout(eval("big_guy_in"),"600");$("#slide1text").css("left","-800px");$("#slide1text").animate({"left":0},600, "easeOutElastic", null);$("#bigGuyPointing").css("left","600px");
$("#bigGuyPointing").animate({"left":600},1000, "linear", null);
$("#slide1").css("display","block");
$("#bigGuyPointing").animate({"left":600},1000, "linear", null);
}

function big_guy_in(event)
{
clearTimeout(timer);
timer = setTimeout(eval("slide1_out"),"6000");
$("#bigGuyPointing").animate({"left":0},600, "easeOutElastic", null);
}

function slide1_out(event)
{
clearTimeout(timer);
timer = setTimeout(eval("slide2_in"),"2000");
$("#slide1text").animate({"left":900},600, "easeInBack", null);
$("#bigGuyPointing").animate({"left":-900},600, "easeInBack", null);
}

function slide2_in(event)
{
clearTimeout(timer);
timer = setTimeout(eval("slide2_textpanels"),"600");
$("#slide2").css("display","block");
$("#slide1").css("display","none");
$("#standingRobot").css("opacity","0");
$("#standingRobot").css("top","500px");
$("#standingRobot").animate({"opacity":1,"top":0},600, "swing", null);
$("#slide2text").css("top","-200px");
$("#slide2text").animate({"top":-200},1000, "linear", null);
$("#vis1").css("top","200px");
$("#vis1").animate({"top":200},1000, "linear", null);
$("#vis2").css("top","-200px");
$("#vis2").animate({"top":-200},1000, "linear", null);
}

function slide2_textpanels(event)
{
clearTimeout(timer);
timer = setTimeout(eval("slide2_out"),"6000");
$("#slide2text").animate({"top":0},300, "swing", null);
$("#vis1").animate({"top":0},300, "swing", null);
$("#vis2").animate({"top":0},300, "swing", null);
}

function slide2_out(event)
{
clearTimeout(timer);
timer = setTimeout(eval("clear_canvas"),"2000");
$("#standingRobot").animate({"top":-200},300, "swing", null);
$("#slide2text").animate({"top":200},300, "swing", null);
$("#vis1").animate({"top":-200},300, "swing", null);
$("#vis2").animate({"top":200},300, "swing", null);
}

clear_canvas();
});

I’ve left out one particular string of code that’s necessary to load the .js file into Glimmer correctly. You’ll note that there is some commented-out code at the very top of the .js file generated by Glimmer:

//Microsoft.Glimmer.Oneway
//<AnimationCollection ...

This code is a duplication of the .js code written by Glimmer, but it’s is only used to enable users to re-open the file in Glimmer. It’s perfectly safe to remove that code, but be aware that you will not be able to reopen the .js file in Glimmer moving forward.

Get To It

For some of you, the best way to learn is to jump right in and look at the code. Again, you can download the full source and use your favorite text-editor to view the code. For others, I hope the above step-by-step tutorial was helpful. As noted earlier, the markup presented above is not the only way to structure this animation, but it’s the way I found easiest to understand.

Have you made the switch to animating with JavaScript? Do you still find yourself using great plugins like Flash or Silverlight? Where do you find you have to choose and what are the deciding factors? Leave a comment below, and be sure to follow us on Twitter @mixonline.

Follow the Conversation

14 comments so far. You should leave one, too.

Design Informer Design Informer said on Aug 12, 2010

Thanks a lot Tim. I don''t really know much about jQuery but I have been trying to learn how to do things like this. Just downloaded the files now and playing around with it. Thanks!

Kris Kowal Kris Kowal said on Aug 13, 2010

Every occurrence of "eval(''x'')" in your examples will work with just "x".

David said on Aug 15, 2010

Is there a full fetched production tool for designers to use? It''s impractical to ask a designer to do good quality animation using code, from scratch. It''s reasonable to do transitional effects, like moving from point a to b. However, animation needs to be done using a GUI production environment. Having too many Dom elements, moving around using CSS is inefficient and slow. Also, it''s difficult to maintain - are you expecting a designer or a programmer to do changes? It offers little advantage over flash - besides it can run on iOS (but I doubt it can achieve adequate FPS, and slows down the performance of the main content, might as well put up a .mov instead). The markup demonstrated are non-semantic anyway, so I guess this is as pointless as doing css3 icons. I''m sorry, I can see some interesting techniques, but the effort should be focused on more useful things instead - focus on the users.

Joshua Lay Joshua Lay said on Aug 15, 2010

Thanks for this Tim,
Looks very cool. I think this is something for me to try out next weekend for fun.

Seems like a very light weight way to implement a banner.

I guess the only thing lost is if people have javascript disabled. Though, at least they''ll see the first part of the sequence.

Tim Aidlin Tim Aidlin said on Aug 16, 2010

Hi all. I''m glad that some of you are finding this post useful. To your concerns above, David, I hear you. I think, though, that there is a place for this sort of animation, and what I''m trying to do here is expose a way to access the power of JavaScript to designers who are fearful of jumping into JavaScript code.

And by using the power of JavaScript -- not necessarily to do "frivilous animations," perhaps -- but in other instances such as accordion-style elements or other "useful" applications, users have a better experience.

This animation might not be "useful to the user," but it -- at the very worst -- might be a fun way to jump into something new. That''s at least the goal here. :-)

Gopal Gopal said on Aug 17, 2010

Opinions like Davids hamper opening new doors and exploring new possibilities. Glimmer clearly has it''s place. This is a great way to invoke light weight animations in web apps to enhance user experience. UX may not be a big deal for people who subscribe to a utilitarian ethos. It needs to be recognized that humans are emotional beings and an engaging experience is based on evoking emotion.

Paul Harrington said on Aug 17, 2010

Why is Glimmer generating all that eval and not even caching the retrieved DOM elements? Don''t claim this helps people learn how to write good jQuery when the generated code is awful.

Karsten Januszewski Karsten Januszewski said on Aug 23, 2010

@Paul Harrington -- I''m the lead developer on Glimmer. I remember adding that eval() code and not liking it one bit, but I had to do it in order for Glimmer to be able to "round trip" -- the ability for Glimmer to "save" an animation and open it back up in the design view. I ultimately justified the decision because the use of eval() in this case does not pose a security risk as it is always just the name of the method in quotes that is passed in the setTimeout call.

As far as caching retrieved DOM elements, I am not entirely sure what you are referring to -- can you tell me more?

Tools will never be able to generate code that is as elegant or as optimized as experienced developers can write. (This is good for our job security, no?) But, I believe there is a place for tools that generate code. The main reason for this is to enable people who don''t write code to do things that they couldn''t otherwise. But an ancillary benefit is that tools that generate code can help bootstrap the learning process, even though the code they generate isn''t always the most optimal way to do something.

Waqas Zahoor Waqas Zahoor said on Sep 2, 2010

Cooooool

Espo said on Sep 15, 2010

I ride the line between Designer and Coder--and think this is excellent.

@David: As far as usability--come on, seriously? What site have you visited lately does not have some sort of banner/masthead that rotates? It is an excellent way to display a lot of info in a small amount of real estate.

As with anything just because you can, doesn''t mean you should. If there is no place for this on the sites you build or design--then don''t use it.

Anders said on Oct 31, 2010

I find it to some extent comical that you promote HTML5 and use Silverlight to show the video. In an article about geting away from Flash and other technics like that.
Flash and Silverlight is basicly the same, that it can''t be used without a plugin on most web browsers. Why not use HTML5 video to show it? Or just plain old Flash, if that is not enough for you.

dale said on Jan 4, 2011

I''ll have to agree with Paul Harrington in that this is not an example of "good" jQuery code. When he is referring to "cached" DOM elements, he means you are referencing $(''#slide1''), $(''#slide2''), etc. many times instead of setting those to variables at the top of the script and then just referencing the variables later on:

var $slide1 = $(''#slide1''), $slide2 = $(''#slide2'');
// some code....
$slide1.css(...); $slide2.animate(...)

Even though this is such a small script, caching the DOM elements still saves some time overall.

Also, since jQuery is extremely chainable, anywhere that a DOM element is referenced twice in a row or more, these can all be concatenated to reduce code bloat.

In terms of using eval - you can set an anonymous function as the first setTimeout argument and then call the function inside that anonymous one:

setTimeout(eval("slide1_out"),"6000")

instead should be:

setTimeout(function () { slide1_out() }, 6000);

This will also shave some time off since it doesn''t need to parse a string then search for the function - it already knows where to look from the onset.

kiev kiev said on Jan 8, 2011

I''m using Jquery instead of flash because it''s better for SEO, search engines and downloading speed for user.
You can place your images on different domain without cookies to speed up loading (parallel downloads).
You can see implementation of this technique on my site http://eshopes.com