Search code examples
jquerycssanimationspritespritely

Spritely - Play CSS sprite forward and backward on click


I'm trying to create a clickable sprite animation that plays forward (frame 0 --> X) on the first click and stop at frame X. Once complete, clicking it would play it in reverse (frame X --> 0) and stop on frame 0. Rinse/repeat.

This jsFiddle has it pretty close: http://jsfiddle.net/ahainen/njHAC/3/

But I'm having a problem: Click the middle circle, and it plays forward. But then clicking the circle upon completion plays it back but ends on the wrong frame. From there, it stays broken.

I'm learning this as I go (graphic designer here), so I'm trying to figure out CSS sprite animations with clicking to animate and rewind. If there's a better way to do it than this, please let me know.

Also, I have a timer on there currently to make it unclickable while animating. I would love it if when the user clicks it (or hovers it), it would just reverse directions and stop on frame 0 or frame X.

Any help would be greatly appreciated, please let me know if I can supply any further information.

The relevant code:

<!DOCTYPE html> 
<html> 
<head> 
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jqueryui.js"></script>
<script type="text/javascript" src="js/spritely.js"></script>
<style>
body {background:#181818;}
.spriteContainer {
    margin: 0 auto;
    width:320px;
    height:240px;
    position:relative;
    padding-top:120px;
    display:block;}
.clickButton {
    width:320px;
    height:240px;
    position:absolute;
    z-index:2;}
.animatedSprite {
    width: 320px;
    height: 240px;
    background-image: url("http://i.imgur.com/aBlIGEh.png");
    display:block;
    position:absolute;
    z-index:1;}
</style>
</head>
<body>
<div class="spriteContainer">
    <div class="clickButton"></div>
    <div class="animatedSprite"></div>
</div>

<script type="text/javascript">
$(document).ready(function() {

var play_index = 0;

$('.clickButton').click(function(){
$('.clickButton').css("display", "none");
    setTimeout(function(){
        $('.clickButton').css("display", "block");
    }, 940);
});


$('.clickButton').click(function(){
    console.log('second function start');

    if(play_index == 0) {
        $('.animatedSprite').sprite({fps: 24, no_of_frames:16, play_frames:16});
        play_index = 1;
    }
    else {
        $('.animatedSprite').sprite({fps: 24, no_of_frames:16, play_frames:16, rewind:true});
        play_index = 0;
    }
});
});
</script>
</body>
</html>

Solution

  • Based on this SO answer:

    This is happening because of the different play_frames values when running the Sprite. Admittedly it is quite confusing. I'll try and explain.

    When you initially call sprite, it will play the first (16) frames. When you mouse out again, it will go back by (15) frames. All is good so far. But things get out of sync, and so when you play the next (16), you are one frame further than expected.

    As a result, you must decrease the play_frames by one after the initial run

    $('.clickButton').click(function(){
        $('.clickButton').css("display", "none");
        setTimeout(function(){
            $('.clickButton').css("display", "block");
        }, 940);
    
        if(play_index == 0) {
            $('.animatedSprite').sprite({fps: 24, no_of_frames:16, 
                                         play_frames:playFrames});
            play_index = 1;
            playFrames = 15;
        }
        else {
            $('.animatedSprite').sprite({fps: 24, no_of_frames:16, 
                                         play_frames:playFrames, rewind:true});
            play_index = 0;
        }   
    });
    

    Updated demo (I combined the click functions)

    As for disabling it during the animation, how you have it is about as good as you can get it. The only thing I might do differently is disabling the click event for the element instead of changing the display, but it's personal preference