How to create an image based dynamic countdown timer with Imagecache
This tutorial is sponsored by the Save Joseph campaign, a grassroots effort to find a good friend and stellar artist a satisfying, creative job in the next 10 days. I know someone in the Drupal community could use this kind of talent. Learn more about the effort at savejoseph.org.
I have 10 days to find my friend a job, and as part of this effort, I wanted to create an image people could use on their web sites that would dynamically change each day. My first thought was that imagecache would be great for this, but there are two issues that make dynamic text in imagecache tricky:
- Imagecahce images are... well... cached. Once they're made, they don't get re-made until you flush the cache.
- Browsers cache images too, so even if the image was refreshed on the server, the client-side image wouldn't change from one day to the next.
I was able to work around these using a couple of interesting techniques. The end result is something that looks like this:

Before you start, you'll need to download the Imagecache Actions module to add the ability to overlay text on an image.
The first step was to create the background image. I created the image in Photoshop with an empty space where the countdown was supposed to go:

Next, I created a new imagecache preset to overlay text. It's down there at the bottom:

I changed the following settings:
- Font size: 9
- X-offset: center
- Y-offset: top+40
- HEX: #FFFFFF
And for the text, I checked the Evaluate text as PHP code box, and used the following code:
$interval = strtotime('August 5, 2010') - time();
$interval = ucwords(format_interval($interval, 2) . ' left');
return $interval;August 5th is my deadline, and what this code does is use the awesome format_interval function to create a string based on a time difference in seconds. I've set the granularity to 2 so that right now it will say 1 Week, 2 Days but in a few days it will say 6 days, 4 hours.
Next, I uploaded the background picture to the theme directory of my site. Then, I used the imagecache theme function to load up the image with the overlay:
theme('imagecache', 'save_joseph_box', path_to_theme() . '/images/save-joseph.png');Then, I put this in a page preprocessing function in template.php and assigned it to a variable that I could use in my theme. This is really temporary code so that I can copy the output, so it could have gone anywhere.
function jc_preprocess_page(&$vars, $node) {
$vars['save_joseph'] = theme('imagecache', 'save_joseph_box', path_to_theme() . '/images/save-joseph.png';
}Then, I just added a print statement in my page.tpl.php page so I could see the image. Embedding this in the page template temporarily allowed me to play with the imagecache settings until I got the font size and positioning right while seeing a preview:
<?php print $save_joseph; ?>Okay, now we have a functioning text overlay that at least is current as of this moment. But, tomorrow, the image will be out of date. So, we need to flush this imagechange to get a re-rendering of the image whenever the text changes. Here's the strategy I used:
- Set up a hook_cron function
- In the function, use the same code above to create a textual output of the date.
- Load a variable that has the last textual output saved (the first time, this will be blank)
- Check if the new time and the previous time are different
- If so, clear the iimagecache
- Save the new text string to the variable we used before
And here's the code to do it:
function common_misc_cron() {
$interval = strtotime('August 5, 2010') - time();
$interval = ucwords(format_interval($interval, 2) . ' left');
$last_time = variable_get('jc_save_time', 0);
if ($interval != $last_time) {
imagecache_preset_flush(array('presetid' => 'save_joseph_box'));
variable_set('jc_save_time', $interval);
}
}Now we'll have an up-to-date image all the time. Except that browsers will cache images for a while, so we need a way to make the browser think it's a unique image every time to pull it fresh from the server. The way we do this is by adding a dynamic query string to the end of the image URL that will change randomly on every page load.
My goal was to make it really easy to put this image on a web page, so I needed a way to bundle this dynamic-ness with the image. So, using PHP to generate this string was out of the question. The way do to it was to use JavaScript to add the query string to the src of the image tag:
<script type="text/javascript">document.getElementById("save_joseph").src =
document.getElementById("save_joseph").src + "?unique=" + new Date().valueOf();</script>For folks that can't use JavaScript (in Facebook and MySpace, for example), I also provided an image that just had the end date on it, so it could be static. Not as cool, but at least functional:

Finally, I added the script with the HTML image output, copied it, and put in in a blog entry so that people could copy and paste the code to use on their sites.
Recent blog entries
Twitter feed:
- Letter to a disgruntled module user http://is.gd/eLI2y1 week ago
- How to easily upgrade Drupal from one minor version to another with a patch file http://is.gd/ezL2s2 weeks ago
- Restarting my mac for the first time in 24 days #fb2 weeks ago
- Why does it always catch me off guard when people don't look like their profile pics? I should be used to this from my internet datin... #fb3 weeks ago
- @rock_soup What command was that?3 weeks ago
- @dale42 A belated agreement about the devil's work in absolute URLs. :)3 weeks ago
- Save the Planet! Well, the Drupal Planet (actually, the Drupal Planet log files) http://is.gd/egxwt3 weeks ago
- The Save Joseph campaign is over, thank you! (plus, summarization of social networking techniques applied) http://is.gd/eb1Y1 #fb4 weeks ago
- @simonsurtees Great re:evernote offer. In next steps I want to improve API and allow for collaborative content creation. Should be fun!4 weeks ago
- Only 12 hours left to Save Joseph - $150 bounty, infinite karma points, excitement abounds! http://savejoseph.org #fb5 weeks ago
Topics
- activism
- apple software
- book reviews
- design
- Drupal
- drupal administration
- drupal community
- drupal events
- drupal modules
- drupal resources
- freaky stuff
- geeky entertainment
- iphone ipod touch
- jquery
- learning
- life hacks
- looping
- maps
- minimalism
- music
- philosophology
- presentations
- productivity
- rambling
- restraint
- software
- theming
- treadmill desk
- usability
- usability testing
- video demonstrations
- web hosting
- original songs
- This American Life
- evernote
Blog archive
- March 2009 (2)
- April 2009 (15)
- May 2009 (10)
- June 2009 (3)
- July 2009 (3)
- August 2009 (6)
- September 2009 (2)
- October 2009 (4)
- November 2009 (3)
- December 2009 (1)
- January 2010 (1)
- March 2010 (1)
- June 2010 (1)
- July 2010 (46)
- August 2010 (5)










Comments
You could get around the JS URL query thing by setting up some expire rules in .htaccess.
So, would you add the expiration in the site that hosts the image? And that would be respected by various browsers? If so, that would be perfect.
Post new comment