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).