In the world of web development, this is ancient. What you see here may no longer be a good idea or in alignment with best practices. I've left the content mostly as-is, besides minor fixes for typos or dead links.
My original post detailing how I recreated Apple's flip-style counter is a popular one, and I get many questions about how to properly implement it. It didn't take long before I saw some shortcomings to the original technique I used, so I thought it was time to revisit my Apple-style counter and make some improvements.
The biggest problem I had with the original counter was that it was restricted to counting in a linear fashion. The background graphic was a massively long image in which we would drop from frame to frame until it hit the bottom and then we'd start back at the top. You had to animate in numerical order (1 → 2 → 3 → 4) or else the animation would jump around and look bad. All you could do was say what number you want to start at, and how fast you want to count. That's it. I found that very limiting—it needed to be able to animate to and from any digit.
In order to animate freely between digits, I needed to break each digit into separate top and bottom pieces, and animate each independently:
So now instead of one huge 35KB graphic, we have two smaller graphics totaling 23KB at the expense of an added HTTP request. I'm OK with that trade-off.
Naturally, having two separate pieces for each digit makes the background image animations more interesting. For example, lets see how the script animates from 0 to 3 (red) and then from 3 to 7 (blue).
The left graphic is the top half of the digit, and the animation sequence is fairly simple. The starting position for each digit is the first slot in each row. Once the top of the digit finishes we animate the bottom half, which you can see in the graphic on the right.
The bottom animation jumps around a bit more, because I wanted the starting position for each bottom to also be in the first slot of each row. In slot 2 there is a shadow to indicate the top half of the digit is halfway through its fall, perpendicular to the screen and invisible. We then jump to the appropriate slot 3, which is the first you can see of the new digit falling into place, followed by the last two jumps to finish the animation.
So the three red jumps would happen first for the top, followed by the four red jumps for the bottom of the digit. Then it would start over for the blue jumps. It is only more complicated conceptually, but in practice only creates one extra background animation action.
The same effect could also be accomplished if all digits were in one long column like they were in my original script, and just shift it up and down rapidly into the correct position. Or you could just join the top and bottom graphics into one large sprite and handle the offsets accordingly in the animation. However, the logic controlling the background-position animations would be more complicated that way, so I broke it into two separate graphics for simplicity's sake.
With my original script, there wasn't much you could actually do with the counter. Its functionality was limited to a "set it and forget it" setup. There was no easy way to manipulate the counter once created. Let's start with that... creating a new counter:
var myCounter = new flipCounter(div, options);
Sample HTML:
<div id="counter" class="flip-counter"></div>
That's all you need for a counter. The ID can be whatever you'd like, but every counter needs the class "flip-counter", because that is what the CSS uses to style the counters.
Sample JavaScript:
var myCounter = new flipCounter("counter", {inc: 23, pace: 500});
The above code creates a counter inside the div with the ID "counter", starting from 0 (default), incrementing by 23, every 500ms, automatically (default).
Now that we have an easier way to set up the counter, there needed to be easy ways to manipulate it, so I created the following methods:
myCounter.setValue(12345);
myCounter.setIncrement(123);
myCounter.setPace(800);
myCounter.setAuto(false);
myCounter.step();
myCounter.add(456);
myCounter.subtract(456);
var value = myCounter.getValue();
incrementTo
or
smartIncrementTo
, which are explained below. Example:
myCounter.stop();
myCounter.incrementTo(12345);
This will increment to 12,345 using the current
pace and
inc values.
myCounter.incrementTo(12345, 10, 400);
This will increment to 12,345 as well, but the increment process will take 10 seconds to complete. The counter will determine the optimal values to use. In the example I've set a desired pace of 400, which the counter will try and stay as close to as possible when finding the optimal values. This method is not chainable.
Update: 11/27/10
Update: 12/5/10
Update: 2/7/11
Updated to work with jQuery 1.5, older versions will not work with v1.5. Animation technique changed.
Update: 4/13/11 – v0.5
I finally added a version number to keep track of changes. Major changes:
Update: 4/19/11 – v0.5.2
bOffset
parameter, explained in the
configuration options.
Update: 5/7/11 – v0.5.3
idPre
parameter removed because was pointless. Each counter needs a unique ID to begin with, so that can be used as the prefix for the digits.
Here's a peek at my progress with removing images from the counter entirely.