Mike Bostock is amazing. I use his D3 library for most of my web visualization work. The documentation is fantastic, the code is clean and concise and he’s created a great little ecosystem of examples on the D3 site and with bl.ocks.org.
I’ve been working on visualizing indoor location activity and one of the views is a live view of individual device locations. To provide some additional context, the view also provides the recent history path (or “tail”) for each device. Getting the path animation correct took a little trial and error. This post describes how I got points and paths to update and animate smoothly using D3.
Roughly, the system works by reporting sensed locations of detected devices at a regular interval. The total number of devices changes as the devices physically enter and exit the range of the sensors. The updates are communicated asynchronously to the server with a simple update record similar to
1
|
|
When the browser sees a new device id, it starts showing the device location on the map. The browser knows the expected longest update interval, and if a device hasn’t been updated by then, it is removed from the map. While the device is being updated, the browser constructs a tail showing previous locations of the device. We would like this tail to represent a fixed duration (e.g. the last 30 seconds). Visually, that means longer tails will correspond to faster moving devices and the absence of a tail means a stationary device.
Using D3, this tail is simply an SVG path that we wish to animate. There is already a really good tutorial on path transitions in D3. But our use doesn’t really fit that pattern. We have a case where we are trying to interpolate paths of different lengths.
1 2 3 4 |
|
After a little trial and error, I found what worked best was to chop up the line into multiple segments and animate each segment individually following the device motion.
1 2 3 4 5 6 |
|
This way, the segment starts at the first point, it then “grows” towards the second point and then finally collapses into the second point providing a smooth animation. To ensure the tail represents the desired duration, I just need to make sure the last transition is delayed for that duration.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
The full gist is available here and it can be seen in action here.