Another short demo before we move on to more complex applications. In this
one I wanted to do something with the HTML5 video element; I had
probably seen something about kaleidoscopes recently so I thought about doing a
video kaleidoscope. Something that would like the screenshot below... That
should be easy!

Actually, it wasn’t too bad.
Although I suspect that it could be done more concisely in SVG (something for a
next episode, I guess) this implementation based on video and
canvas, with an additional help of CSS 2D Transforms, is really
simple conceptually. And it will exercise your processor quite a bit in the
process...
Sampling video
As the screenshot above shows, our kaleidoscope is a circle rotating on its own or following the cursor, divided in six “slices”, where each slice contains the same picture, rotating on its own, and flipped. A first approach was to have six video elements playing the same content at once, but it proved clearly impractical to synchronize, and without looking too much into it, masking and overlaying different videos seemed pretty tricky.
Fortunately, we can easily sample the video by drawing the
current frame in a canvas element (with the
drawImage() method of a 2D drawing context, and using a
video element as the first argument.) We can draw our kaleidoscope
in a canvas element, with a single video playing in the
background. The video is playing behind the canvas so that we
don’t see it but can still hear it and of course sample it. And although we
could draw all six slices in the same canvas, I have chosen to
draw the same picture in six different canvases and let CSS do the rest. We can
describe the full process in four steps.
- Set up a
videoelement, and wait for it to start (see below.) - Set up six
canvaselements. For eachcanvas, we’ll have an initial clipping mask which will produce the shape of the slice. This needs to be done only once as it operates on the drawing context of the canvas. The tricky part here is to understand how to use thearcTo()drawing primitive, and honestly I’m not quite sure that I do but it seems to work out well enough. - At a given rate (something like 15-30 frames per seconds, which is
sufficient for video), draw the current video image in every
canvas. We set a new context before drawing where we apply a rotation incrementally so that the image in each slice appears to rotate on its own. - Set the
transformstyle property (or rather-webkit-transformproperty) of eachcanvaselement to rotate by increments 60 degrees, and flip around the X-axis for every othercanvas(so that the symmetry is respected.) Since the whole kaleidoscope rotates, we add the current rotation angle of the kaleidoscope to every slice to achieve global rotation.
Cross-browser issues
The current demo only supports Safari. I haven’t had much success playing audio or video in Chrome, so maybe some day it will work. Firefox should work, but needs a few fixes:
- The main issue is that Safari and Firefox do not support the same media formats. This means that a fallback OGG video is necessary for Firefox.
- Media elements generate an awful lot of events, and because they can be
quite large it means that we need to wait for enough data to be available
before we can start playback. It may take a while even knowing what the size of
the video is, which is necessary to set up the canvases, drawing contexts,
&c. In the current implementation I wait for the
canplaythroughevent before starting playback, which means that the whole video should be playable. Unfortunately I wasn’t able to catch that event in Firefox. I will write a bit more on this topic later and hopefully fix this demo to work in Firefox. - As in the poetry magnets
demo, we need to add support for the
-moz-transformstyle property for CSS transforms.
That’s all for now; on the next episode we’ll see more canvas animation action.
Update: these issues have now been addressed.
