In this post I’ll be describing my thoughts and methods when developing the Hawaiian Earring experiment which uses HTML5 canvas.
If you don’t want to read about all the technical mumbo jumbo you can use the link below to go straight to the good stuff. The post mortem continues below.
View the Hawaiian Earring Experiment.
Background and inspiration
I’m a big fan of recursion and procedural content generation. Recursive routines can produce remarkable results from minuscule pieces of code. When not completely debugged, these small ingenious routines can crash spectacularly if the termination case hasn’t been handled correctly.
Wikipedia defines recursion as:
Recursion in computer science is a method where the solution to a problem depends on solutions to smaller instances of the same problem. The approach can be applied to many types of problems, and is one of the central ideas of computer science.
Google manages to slip in a nerdy joke if you search for recursion. The “did you mean” feature, which is normally used for spelling mistake suggestions, will say “Did you mean: recursion” and links back to itself. As the image below illustrates.

Recursive techniques have often been used in graphical demonstrations. They are the ideal choice when a small executable size is necessary. The “Hello World!” equivalent of recursive graphical demonstrations is the Mandelbrot set fractal. This is named after the mathematician Benoît Mandelbrot, who studied and popularized it. Other common recursion graphic demonstrations are the Menger Sponge, the Sierpinski Carpet and the Koch Snowflake.

I don’t think that humans are naturally conditioned to search for recursive solutions to problems. It requires a different approach than how we usually break a task down into separate steps. Recursive decomposition is usually the hard part, that is determining where the self similarity lies. The next step is to break the the problem into a smaller form which if reused can solve the overall problem. Once you have the plan of how to make the initial task smaller and simpler, following it through to it’s logical conclusion is usually easy.
While browsing Wikipedia, I came across the Hawaiian Earring page. The text there is very dry but what I did find striking was a small wire frame image of the Hawaiian Earring.
To my eye, this looked like something that could easily be calculated with recursion. Each of the inner circles could be generated from known information about it’s parent. The recursion should terminate when the radius of the circle becomes too small.
Knowing when to stop or when enough is enough
The development would quick and painless because I was already familiar with the concepts and I had some thoughts how I could make it more interesting than plain wireframes. Before starting I decided to make a short list of things that I wanted to achieve with this experiment.
-
Interactive
The user should be able to interact with the experiment.
-
Fast
It should run as fast as the browser allows and respond quickly to user input.
-
Try something new
To keep me interested in the development and to motivate me to blog about it.
With these goals in mind, I began the development of the Hawaiian Earring. In the next section I’ll briefly go over points of interest in the source code.
requestAnimationFrame
If you’ve ever tried to do smooth animation in the browser, there’s a good chance that you’ve used the setTimeOut() or the setInterval() methods in JavaScript. These are used to trigger your update function every few milliseconds.
Now if you want your animations to run as fast as possible, there’s a better way to do things with requestAnimationFrame. The code below shows how it’s initialised. This is called at the end of the update() function when so that the browser will schedule the next update as soon as possible.
if ( !window.requestAnimationFrame ) { window.requestAnimationFrame = ( function() { return window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || // comment out if FF4 is slow (it caps framerate at ~30fps: https://bugzilla.mozilla.org/show_bug.cgi?id=630127) window.oRequestAnimationFrame || window.msRequestAnimationFrame || function( /* function FrameRequestCallback */ callback, /* DOMElement Element */ element ) { window.setTimeout( callback, 1000 / 60 ); }; } )(); }
For more detailed information on requestAnimationFrame, take a look at Paul Irish’s blog post.
addEventListener
This experiment uses event listeners to change parameters of the Hawaiian Earring. One event listener is used to detect when the mouse is moved over the canvas area. Another event listener is used to process mouse clicks in the canvas area. Below is a cross browser method that will register an event listener.
addListener: function (type, target, fn) { if(window.addEventListener) { target.addEventListener(type, fn, false); } else { target.attachEvent( "on" + type, function (e) { fn.apply(target, [e]); } ); } },
Clearing the canvas
In this experiment there are two different drawing modes used, wireframe and filled. The wireframe mode requires a clean canvas each frame. The easiest way to do this is by changing the canvas dimensions to a different value and then back again. This will flood fill the canvas with it’s background colour. This can be done with these two lines of JavaScript.
this.canvas.width = 1; this.canvas.width = this.canvasSize;
For the filled drawing mode, I wanted a motion blur type effect with softer edges. I achieved this by retaining the canvas image from the previous frame and making it darker. This was done by setting the globalCompositeOperation mode to “darker” and then drawing a transparent rectangle over the whole canvas area. This can be done with the three lines of JavaScript below.
ctx.globalCompositeOperation = "darker"; ctx.fillStyle="rgba(0, 0, 0, 0.382)"; ctx.fillRect(0, 0, this.canvasSize, this.canvasSize);
The good…
The end result was reached quickly. The experiment runs smoothly and responds quickly to user interaction. There’s a good contrast between the wireframe and the filled drawing modes. The angle tweak in the alternative mode makes the motion interesting.
The bad…
There’s no recursion function calls in this final version. What?! Who’s to blame for this? Heads will roll! In my quest for higher frame rates I optimised out the recursion and obtain the same result using iteration instead. This tiny increase in speed isn’t noticeable in this experiment because so few circles are drawn. I couldn’t think of a good reason to revert back to the recursion version, other than that was the original plan.
The ugly…
When profiling this experiment it was obvious that the main bottleneck was in the canvas drawing. Rather than in the calculation of all the circle mid points and radii. So I fixed the size of the canvas to 256 pixels by 256 pixels to ensure a decent frame rate on all display sizes.
With more time I would have liked to include functionality to dynamically set the canvas size. This would determine the largest resolution possible that the user’s browser could handle smoothly. With this added functionality in place it would be easy to resize the canvas when the user’s browser window size changes.
Closing comments
Overall I’m pleased with how this first blogged experiment has turned out. Even if the final result was achieved using different methods than I originally intended.
Earlier in this post I’ve only touched on a few sections of the source code that may be of general interest. If you want to see how the user interaction is processed or how the Hawaiian Earring is constructed, the complete source for this experiment is available on github.
View the Hawaiian Earring experiment
Download the Hawaiian Earring source code from github