Our team of UX designers, digital strategists and developers began our search for inspiration, sharing ideas and analyzing what made us all sit back and say "Wow!" (Some of the things that did this for us included http://360langstrasse.sf.tv/page/http://kyan.com/http://www.socialsummit.cz/en and http://davegamache.com/.) A few specific technologies stood out to us - frame-by-frame video (JPEG sequence) scrubbing, parallax effects and, of course, responsive design.

Once we had defined our goal and a written rough draft of the functionality requirements, we began creating our first working prototype. Our road to the initial alpha version was almost a single step. Within a day we had extracted a video, converted each frame to compressed JPEG files and setup our canvas to stretch the first image to completely fill the viewport with a method called zoom cropping (zooming to the point of filling a viewport while maintaining aspect ratio). We turned the web page into a virtual timeline and wrote Javascript code that would animate the frames based on how far down the page you scrolled. It didn't take long between developing this first initial working prototype and getting the support and approval from our client. Ambition was high, our goals were clear and we were setting out to build one of the most amazing experiences we could imagine.

The journey from our initial prototype to the final site was long and we looked at a wide variety of ways to animate the video frames before we found something that would work reliably in all of the browsers we were supporting. Whenever you push the limits of technology, you must constantly compromise how you want to do something in order for it to actually work in the real world.

We owe much of the success of our final version to the information in an article written by Paul Irish. With this method of animation, "the browser can optimize concurrent animations together into a single reflow and repaint cycle, leading to higher fidelity animation". Which is exactly what we needed to make this work and reduce CPU load and increase battery life for our mobile users!

Here's a code snippet:

window.requestAnimFrame = (function(){
   return  window.requestAnimationFrame       || 
   window.webkitRequestAnimationFrame || 
   window.mozRequestAnimationFrame    || 
   window.oRequestAnimationFrame      ||  
   window.msRequestAnimationFrame     || 
   function( callback ){
       window.setTimeout(callback, 1000 / 60);
   };
})();

(function animloop(){
   requestAnimFrame(animloop);
   targetStep = Math.max( Math.round( getYOffset() / 30 ) , 1 ); // what frame 
to animate to
   if(targetStep != step ) { step += (targetStep - step) / 5; } // increment the 
step until we arrive at the target step
   changeFrame();
})();

function changeFrame() {
   var thisStep = Math.round(step); // calculate the frame number
   if(images.length > 0 && images[thisStep]) { // if the image exists in the array
       if(images[thisStep].complete) { // if the image is downloaded and ready
           $('#video').attr('src',images[thisStep].src); // change the source of our 
placeholder image
       }
   }
}


Sharing knowledge and information with others is one of the biggest reasons humans have been capable of technological progress. The development team and executives here at Emerge Interactive share this philosophy and strongly support open-source communities, which is why we decided to create this demonstration to share with others who might be interested. We also want to say a special thanks to Paul Irish for the quick study he provided. The deceptively small article he posted has propelled the capabilities of the web forward by leaps and bounds.

We hope you've enjoyed reading about our experience and that you will also enjoy reverse engineering and manipulating the code that we've shared for you:

View Demo | Download Sample Files (ZIP) | Fork on Github

Note: There are several things to keep in mind as you attempt to modify this example to use your own JPEG image sequence and customize it to fit your implementation:

1. Image optimization is a critical piece of making this work. We ended up resizing each of the images to about 400 pixels tall and compressed them to a target file size of about 15-20KB each.
2. Keep your JPEG sequence fairly short, each JPEG in the sequence is a file that a user has to download in order to display. Users on slower internet connections could have a hard time or be incapable of viewing your page if you don't focus on optimization.
3. Try not to have hard cuts in the video. Seamless image transitions are key to making this effect a smooth experience for visitors. We experimented with a wide array of footage, and recommend you do the same. Once you have your setup configured, it's easy to swap out the frames for new image sequences.
4. You need to preload your images for this work or you'll experience delay as each new image is called and the browser attempts to display each frame. Because of this, the experience can be jarring on a slow computer or through a slow internet connection. Adding conditional configurations for older browsers that reduce the frame-rate (skip every other frame in IE 8 or less, for example) and that reduce the total number of frames is highly recommended. Taking further steps to detect a user's bandwidth and download speed is also very effective to improve the responsiveness and usability of an application like this.
5. Noscript fallbacks are good practice. Using CSS to size your initial image to fit the viewport ensures that users without Javascript enabled will still be able to use your web site and experience the rest of your content, even though they won't see the scrubbing effect.
6. Adding a tiling grid pattern overlay on top of your video images is a great way to hide some of the artifacts that are visible after stretching a small, heavily compressed image to fit a large browser viewport. You can also use this overlaid image to lighten, darken or colorize the video JPEGs so the content on the top layers is more readable.

That's it for now! Watch, like and follow Emerge Interactive for more demonstrations, lessons and code snippets that we'll be releasing in the weeks and months to come.

comments powered by Disqus