Controlling animated gifs with JavaScript is not possible, but using jQuery the same effect can be accomplished with this “filmstrip” technique.

Making cool Flash-like animated buttons without using Flash has lately become a reality with the JavaScript frameworks like Dojo, Mootools, Prototype and jQuery. A List Apart has a nice article on the subject. But the solutions I’ve seen all limit them to animating a CSS parameter over time. I wanted to take it a step further.

I wanted to run a little film sequence on mouseover, like an animated GIF. But using an animated GIF was no option, as they can not be controlled in terms of starting and stopping them. So I looked to the most classic form of animation, the filmstrip. Stacking all frames on top of each other in one image and using jQuery, it is possible to create an animation with just changing the y-value of background position. See the example here.

Here’s the code:

HTML

<div class="wrapper">
    <ul class="buttons">
        <li><a href="#">Link1</a></li>
        <li><a href="#">Link2</a></li>    
        <li><a href="#">Link3</a></li>
        <li><a href="#">Link4</a></li>
    </ul>
</div>

<script type="text/javascript">
    $(document).ready(function() {
        filmstripButtons(".buttons", 21, 50, 30);
    });
</script>

As you can see we have a simple unordered list representing the buttons. On that list we run a jQuery script called “filmstripButtons, which adds the mouseover event. Parameters passed to the script are the classname of the list, the number of frames in the movie, frames height and delay in milliseconds.

CSS

body {
   background-color      : #6a7cbf;
}

.wrapper {
   width                 : 404px;
   height                : 50px;
   margin                : 100px auto;
}

.buttons {
   list-style            : none;
   padding               : 0;
   margin                : 0;
}

.buttons li {
   float                 : left;
   width                 : 100px;
   height                : 50px;
   padding               : 0;
   margin                : 0;
   background            : url(../img/btnAnim.png) no-repeat;
   text-align            : center;
}

.buttons li a {
   font-family           : 'Trebuchet MS', Arial, sans-serif;
   color                 : #fff;
}

As you can see, the CSS is straightforward. Worth noticing is the “li”, where the background image – our filmstrip – is defined, as well as frame height and width.

JavaScript / jQuery

The javascript is explained with comment inside the code.

function filmstripButtons(parentElem, slidesCount, slidesHeight, speed) {
    // create an array for the timers
    var t = new Array();

    // iterate through each button
    $(parentElem).children("li").each(function() {
        // if the buttons "li" element doesn't haev an ID, create a random and assign it
        if($(this).attr("id")=="") {
            $(this).attr("id",randID());
        }

        // make sure that each buttons background-position is set to 0 and in pixels
        $(this).css({backgroundPosition: "0px 0px"});

        // add the mouseenter event to the button
        $(this).mouseenter(function() {
            element=$(this);
            id=element.attr("id");

            // Each button will need it's own timer. These are stored in an array
            // and identified by the buttons ID. The timer calls the "animate" function
            // with the timeout delay passed to the function in the "speed" variable
            t[id] = setTimeout(function() {animate(element, slidesCount, slidesHeight, speed, t)}, speed);
        });
   });
}

function animate(element, slidesCount, slidesHeight, speed, t) {
    // Extract the y-coord from bg-pos and remove "px"
    var curBgPos = element.css('backgroundPosition').split(" ")[1];
    curBgPos = curBgPos.replace(/px,*\)*/g,"");

    // Check if the end of the filmstrip is reached
    if(curBgPos<=(-(slidesCount * slidesHeight))) {
        // If the end is reached, restore fimstrip to the beginning
        // and do NOT initiate a new timeout
        element.css({backgroundPosition: "0px 0px"});        
    } else {
        // If the end is not reached, move the background one frame
        // and initiate a new timeout
        element.css({backgroundPosition: "0px "+(curBgPos-slidesHeight)+"px"});
        id=element.attr("id");
        t[id] = setTimeout(function() {animate(element, slidesCount, slidesHeight, speed, t)}, speed);
    }
}

function randID() {
    // This function will generate a random ID
    var x = Math.ceil(Math.random()*1000000000);
    return "id_"+x;
}

Conclusion

The technique could be refined with mouseout and onclick events.
Download the project here.

Enjoy.

Posted Monday, November 23rd, 2009 at 12:49 pm
Filed Under Category: CSS, JavaScript
You can leave a response, or trackback from your own site.

0

Leave a Reply