Anagranimation

The name of this website is an anagram. It's possible to rearrange all of the letters in the neural bit to form brian hulette. That's a simple concept I set out to illustrate concisely with the site's logo.

For the first iteration of this webpage, way back when I was in late high school and early college (ca. 2007), I just pulled up the Gimp, which I had probably learned to use just the previous week, and drew up the following image. It shows the two words in bright letters and a few intermediate iterations with letters swapped in between them.

Original logo

This gets the job done, but it leaves a lot to be desired.

After I moved to my new static site I didn't bring the original logo, so I was stuck without a concise illustration for a while... until I learned about D3. After reading some of Mike Bostock's excellent blog posts about selections, object constancy, and transitions1, I realized that an anagram is a perfect use case for D3's data binding model.

My basic idea was to take the letters in a string and bind them to svg:text elements, which are then positioned based on their index in the string. Later a new string, which is an anagram of the first, is bound to the elements. The positions of the elements are updated, with the transition in between animated. Then we can toggle back and forth between the two strings to our heart's content.

Confused? So was I. Let's start from the beginning.

Binding characters to svg:text Elements

We'll start by just drawing a string using a bunch of separate svg:text elements. We create a selecton of svg:text elements, then bind the string data to the selction. Then we grab the enter() selection to get just the elements that are new, which is all of them in this case. We then set the elements' text to that datum, and set their x positions based on the character's position in the string.

Binding a new String

Once the original string has been bound we can bind a new string that has all of the same characters. Then we just recompute the x attribute based on the new indices in the string.

Unfortunately there's one catch: by default D3 will just check the new characters for equality with the old characters to bind the new data. Normally this is a reasonable behavior, but in this case it will cause problems since we have duplicates of the same character. To solve this problem I wrote a function, transform() that turns a string into a list of objects. Each object has one attribute indicating the actual character, and another attribute that is an index to ensures it is unique.

For example, transform('the neural bit') would return:

[{c: 't', i: 0},
 {c: 'h', i: 0},
 {c: 'e', i: 0},
 {c: ' ', i: 0},
 {c: 'n', i: 0},
 {c: 'e', i: 1},
 ...
 {c: 'i', i: 0},
 {c: 't', i: 1}]

Note that the second e and the second t both have an index of 1, to distinguish them from the first occurrences.

With these new objects D3's default behavior will be sufficient to ensure a reasonable mapping from the old string to the new string. The first t will be associated with the other first t and the second e will be associated with the other second e, and so on.

The following example uses the new transformed strings to toggle between the neural bit and brian hulette using a timer. Note that I only have to set the text of each element once, in the initial svg.selectAll(). Within the setInterval() function, all I do is bind the toggled string and update the x attribute based on the character's position in the new string.

Well that result is... underwhelming. You really can't tell that those are actually the same svg:text elements each time it toggles. It just looks like we're swapping out a new string. We need to animate the transition between each state...

Adding Transitions

Fortunately D3 makes this easy - all we have to do is add a .transition() call to the method chain before binding an attribute to some new function, and D3 handles the rest! It will set keyframes and set up easing functions all by itself. You can read a lot more about the transition capability in the docs, I'm only scratching the surface here.

In the following example, I also added a call to .duration(), which makes sure the animation takes one second, and a call to attrTween() which defines intermediate values for the y attribute. This makes the characters follow a parabolic trajectory.

In the example below you can see these changes reflected after the svg.selectAll() call within setInterval().

This is a pretty great little animation, and I thought about stopping here. It does get the point across, but I still wasn't totally happy with it. The letters are clearly "on rails", and they cut through each other's paths. Fortunately, I found way to make the animation much more dynamic.

D3 Force Layout

Yet again, I followed Mike Bostock's lead here. I knew I wanted to use a force layout to create something like his Multi-Foci Force Layout. My idea was that each character would have a focus associated with it, which is set based on the letter's position in the string. I then used the same approach as Bostock's Multi-Foci Layout to attract each character to its focus. When toggling strings we simply change these focus positions and the letters will shuffle around. To make things more interesting I also added a few more features:

You can see this Force Layout implementation, in all its gory detail, in the jsfiddle below or on github. If you'd rather just see it in action, scroll up and mouse over my logo!

  1. If you aren't familiar with D3 and you'd like to be I would highly recommend you start with some of these posts