Since we’re based in (mostly-) sunny San Francisco, Flickr’s code monkeys will be away for a few days eating excessive amounts of turkey and being appropriately thankful. Before heading off with friends and family, I thought I’d share a bit of “seasonal” JavaScript we have on the site, and a few notes about its inner workings.
Fun is Good
We build a lot of “serious” stuff at Flickr HQ, but we also recognize why it’s crucial that we save some time for the small things, the goofy and occasionally-irreverent parts of the site that remind people of a playful spirit. Outside of our daily work, many of us have our own personal geekery going on. It’s no coincidence that shiny, and even silly things people tinker with and build in their own time sometimes bleed over and become features or elements on Flickr; ideally, great ideas come from all sorts of places.
Let It Snow
Last holiday season, we got around to making it snow on photo pages – just for the fun of it. If you happen to be on a photo.gne page and add ?snow=1, it might still even work.. We’ve also used a variant of the effect in the past for beta feature sign-up sequences, complete with cheesy MIDI renderings of “The Girl From Ipanema.” Again, this was “just because”; sometimes the web is most entertaining when it’s most unexpected. If you can occasionally make your users smile, giggle and laugh when using your site, chances are you’re doing something right – or, you’re running a comedy site that’s going downhill.
Wait, Snow is Hard
The snow effect was a JavaScript experiment made strictly as a test of DOM-2 event handlers, PNG and animation performance. Or, viewed in a more-cynical light, it was an evil plot to pollute websites with falling animated .GIFs and light CPUs on fire world web-wide.
To achieve a realistic effect, each snowflake has its own size, “weight” and x/y velocity properties which can be affected by “wind”. A slight parallax effect is achieved by the notion that larger flakes are closer to the screen and move faster, and so on.
It may not be surprising to note that it’s still expensive CPU-wise to animate many individual elements simultaneously. The effect is much smoother and has higher frame-rates these days when compared to early versions from 2003, but even modern browsers will readily eat up 50% CPU while running the effect. That said, the animation is keyed off of a single setInterval()-style loop with a low interval, so it will effectively try to run as fast as it can.
Revisiting Performance
“In theory there is no difference between theory and practice. But, in practice, there is.” – Yogi Berra
I had a theory that using text elements might be more efficient than image-based snow to animate, so I made the switch to using elements with the bullet entity • instead of PNGs with alpha transparency. No noticeable improvement was actually seen, despite my theories about drawing and moving images; HTTP requests were being saved, but the browser was still doing a lot of redraw or reflow work despite the elements using either absolute or fixed positioning. On my netbook-esque laptop with Firefox 3.5 under WinXP, animation would “freeze” when scrolling the window with position:fixed elements – presumably because my single interval-based JavaScript timer was blocked from running while scrolling was active.
In retrospect, what might be more efficient for overall CPU use is a number of absolutely-positioned “sheets” using a tiling background image with a pattern of snow. Each sheet of snow would move at the same speed and angle, but the number of unique elements being animated would be drastically reduced. JavaScript-based animation is not a science in any case, and having a large number of elements actively moving can significantly impact browser responsiveness. While this is not a common web use case for animation, it is interesting to note how the different browsers handle it.
Make Fun Stuff, and Learn!
Much of what I enjoy about front-end engineering is the challenge. I’ve learned a lot about browser performance and quirks just from prototypes and experiments, which can then be used in real production work.
While cross-browser layout and performance varies, it’s also rewarding to work on the occasional crazy idea or silly prototype and then refine it, features and quality-wise, to a point where it’s ready for a production site somewhere. JavaScript-based snow is at best a “perennial” feature, but the process of thinking about how to make something different and new work, and work well (theory) – and then researching, testing and hacking away to actually do it (practice) – is where the learning comes in.