Apple introduced Live Photos with iOS 9, a feature that automatically associates a short video with every picture that's taken. I was skeptical at first, wondering how relevant this would be for static content; and it turns out not to be all that compelling for some kinds of photos. But for dynamic scenes or people in motion, the video can add some really interesting context!
Live Photos on iOS are (naturally) smooth and easy to use. I wondered what it
might be like to bring a similar experience to the web. I'd also been looking
for a reason to explore Web Components.
And so live-photo-web was born!
Click here for a simple demonstration of the techniques described below.
An easy way to implement the Live Photo effect is to start with a standard
img element
and swap out it's src property with an
animated gif when the user
touches the image or hovers the mouse over it. This is easy to do with a bit of
JavaScript and some code to attach the event handlers - though it's nice to
package everything up for reuse. Fortunately, there's an emerging standard that
enables just that: Web Components. And while browser support for web components
is not yet universal, a handy
polyfill exists thanks to WebComponents.org. It
ends up being straightforward to write a simple extension to the img element
that listens to the mouseenter, mouseleave, touchstart, touchend, and
touchcancel events to implement the desired behavior. Using it is easy; just
decorate an existing img element with the is syntax and make sure a gif
image of the same name exists alongside the original src image.
Here's what it looks like in practice:
<img is="live-photo-image" src="sample.jpg"/>See live-photo-image.js for the complete implementation.
gif images are convenient because they're natively supported by the img tag
in all browsers, automatically play themselves, and automatically loop. However,
the gif format is poorly suited to storing photo-realistic movies, so file
size can be very large (5.19 MB in the example). An (optional) enhancement is
to have the browser prefetch the gif image after loading the page so it will
already be cached by the time it's needed. The
link/rel/prefetch tag
is ideal for this and looks like the following:
<link rel="prefetch" href="sample.gif"/>Enhancing an img element is simple enough, but creating a dedicated Live
Photo element offers even more possibilities. In particular, instead of swapping
out the src to show a gif, the code can swap out the entire img for a
video element
to get better quality, much smaller file size - and sound! Add the same
mouse/touch logic as above, drop an mp4 video alongside the original src
image, update the HTML, and you end up with a much richer experience.
Here's what it looks like in practice:
<live-photo-element src="sample.jpg"></live-photo-element>See live-photo-element.js for the complete implementation.
Unfortunately, there are two drawbacks with this approach. The first is that
video and mp4 are not as universally supported as gif, so there are some
browsers where things don't work smoothly (or possibly at all). The second
is that the format for Live Photo movies, mov, is not natively supported by
all platforms (notably Windows), so it's a good idea to transcode the mov to
a more popular format like mp4. On the plus side, transcoding is a good
opportunity to resize the movie to fit the target scenario - leading to a very
compact file size (just 329 KB in the example).