- Open the demo in any modern browser with proper 3D CSS transformation support (Chrome, Safari, or Firefox).
- Choose your favorite image sharing services (Flickr, 500px, Instagram, or Dribbble).
- Watch the photos animate vertically, then fully rotate horizontally at regular intervals.
- Use your arrow keys to rotate the images manually.
The demo wasn’t all that technically challenging, but there were some interesting issues along the way.
Compensating for Perspective
To create the illusion of perspective and depth, objects that are supposed to be further away are scaled down. As a result, when you create a bunch of images with random X, Y, and Z coordinates, they tend to form a tunnel-like shape on the screen, congregating around the centre which isn’t very pleasing to the eye (a). To compensate, we explicitly shift the images to the sides to make them appear more evenly distributed (b).
For all UI graphics, we used SVG. SVG has several advantages over images:
- For our simple case, SVG icons were much smaller than PNGs.
- SVG is much easier to script: change color, rotate, add glow, etc.
- Since SVG graphics are vectors, they look better on displays with high resolutions.
Math.random() is Not Very Random
We found that randomizing the horizontal position makes images sometimes crowd around one particular side of the screen. To compensate, we divide screen into columns and ensure that images appear in all columns. We then “randomize” the X, Y, and Z coordinates within each column. The result is that the images are much more evenly distributed.
Keeping Images Out of Your Face
When the images rotate around the Y axis, they get too close to the camera which makes them look a bit ugly and disturbing. To make it look more appealing, we add an animation that pulls the camera back at the beginning of the rotation, then returns it to where it was at the end. The effect is subtle, but much less jarring and generally more pleasing.
To work around XHR crossdomain security restrictions, we decided to use JSONP, but there was a nasty surprise: the 500px API doesn’t actually support JSONP. To workaround this issue, we use YQL to pull JSON from 500px and to convert it into JSONP.
The main issue was, of course, the performance of the animation. The animation itself is relatively simple code that uses
requestAnimationFrame(). The animation works by combining all the animations’ CSS transformations (vertical and horizontal movement as well as rotation) into a matrix representation that later gets applied using
matrix3d(). Operating via