If you take a look at these animations they may look deceptively simple and in essence they are but the road that leads to them is quite bumpy. Let me share the ride.
When it comes to animations animated GIFs are the first thing that probably pop into most people's minds. Unfortunately, they tend to be very large files that download slowly, especially in the case of high-resolution animations featuring high frame rates. But what alternatives exist?
SVG! Unlimited resolution, unlimited frame rate, minimum size. SVG is great but just like in the case of videos it's quite tricky to make them responsive. Thank God there are some excellent writeups out there explaining how to make SVGs responsive.
I really wanted to define SVG animations in a declarative manner so I went with SMIL which stands for synchronized multimedia integration language. It's essentially a set of tags and attributes to describe animations within SVGs. It wasn't trivial to chain a sequence of animations together but eventually I made it work. Then came cross-browser testing and the realization that Internet Explorer (unsurprisingly) doesn't support SMIL. No problem, there's a polyfill for that! Except that it doesn't work well so SMIL can go down the toilet.
Snap.svg to the rescue! I put distinctive IDs on the various elements to be animated. The most important objects are the left hand and right hand elements and there were a couple of target points outside of the alphanumeric area of the keyboard for the hands to reach out. Being able to animate things algorithmically, I randomized hand movements which resulted in a lively moving pattern that is quite enjoyable to watch.
Cross-browser testing revealed a bug that was hard to debug: On the stock Android browser when scrolling downwards only the first SVG started to animate, all the others were not moving. I used Weinre to debug this issue and it turned out that the stock Android browser didn't like that I reused the same IDs in distinct SVGs. Inline SVGs are all part of the same DOM so this is somewhat understandable even though other browsers handle this situation well. Another weirdness is that when reloading the page in the stock Android browser and scrolling from the bottom towards the top the animations start as expected. Anyways, I ended up using classes instead of IDs to match elements which solved this problem.
I noticed that animations were always running on the page, burning the CPU all the time so I started to think how to reduce CPU usage. jQuery inview plugin to the rescue! I wanted to explicitly pause / resume animations when they go outside/inside of the viewport. For that ideally one should use the pause() and resume() methods of the mina object, except that Snap.svg is buggy in this respect so I ended up using Element.stop() and Element.animate().
I also wanted the animations to lazy-load when the user scrolls before them by 200px but this the jQuery inview plugin didn't support offsets. Luckily, I found an unmerged pull request in the repo that implemented this exact feature. Lazy-loading SVGs doesn't exactly work the way it does with traditional images because when animating SVGs, they must be included inline for the individual SVG elements to be separately accessible in the DOM. I could make this work with Snap.load() and Element.append().
Animations are buttery smooth on desktop machines but rather jaggy on mobile devices. It understandable because SVG animations are quite computationally intensive, especially when there are more of them in the view and are topped with JavaScript code that computes target coordinates real-time. Unfortunately, I cannot improve the situation any further.
Low and behold, you can check the final animation code in a GitHub Gist for your viewing pleasure.
"Was it worth all the hassle?" - you may ask. Even though it started as a simple addition to the site it consumed a significant amount of my time which could have been better spent on designing the next prototype. A part of me wishes to recover the time spent but on the other hand I'm a firm believer that it's critical to present products and ideas in the most digestable and intuitive way possible for the people to get their essence. In this very spirit it wasn't a waste of time after all but I surely don't wanna touch the site for a while.
Hope you enjoyed this writeup. I'm back developing the next prototype along with András. We're gonna make another significant improvement to the site soon (which won't consume my time) and we expect it to blow people away. Excited!