A swiss railway clock in D3.js

Screen Shot 2015-06-05 at 5.26.54 PM

 

The other day I saw this cool JavaScript+CSS clock and I immediately thought that I wanted to create an analog clock in D3.js. First of all as an exercise, but also with the aim —perhaps— of smuggling it in to a future dashboard 😉

It seemed straightforward: just paint the clock and re-paint it each second. Right? Well, yes if you’re lazy. The better way is to paint the clock and periodically rotate the hands.

As with most things on the internet, turns out I was late to the party. Some much more clever people have built D3 clocks and even a multi-clock D3 visualization for displaying multiple time zones.

Good. I had some ideas and a starting point.

I’m in love with the Swiss Federal Railways (SBB) clock, designed by Hans Hilfiker. It’s an emblem of the most effective train system in the world, and a testimony of exquisite swiss modernism. I wanted to make that.

There’s already an SVG visualization of the SBB clock (here’s the code). As I was checking it out, it made me realize for the first time that the axis of rotation is not at the end of the hands, but like at 10% of its length. And that extra length is different for the seconds hand. Also, that ball at the end of the seconds hand was going to be tricky.

As with all great designs of that era, everything is proportional in that clock. I noticed that I would be able to derive all the measurements from the width of the minute ticks. So I defined a starting measurement unit and multiplied away!

The key for doing the hands rotation in D3 is to enclose each hand in its own g element and rotate those g elements using setInterval. The rotation of the hands in the SBB clock is smooth, and thankfully D3 offers transitions for seamless interpolations.

The seconds and minutes hands have to rotate 6˚ each time (360˚÷60) and the hours hand has to rotate 30˚. Since the clock shows only 12 hours, you have to multiply 30˚ by the modulo 12 of the hours.

   
clockHand.transition().duration(1000).ease('linear').attr('transform', function(d,i) {
	if (d.unit==='hours'){
		return 'rotate('+d.numeric%12 * 30+')';
	} else {
		return 'rotate('+d.numeric * 6+')';
	}
});

I was able to quickly put together a very rudimentary version and tweak the design little by little. Then I decided not to waste my first tests, got a little bit carried away and externalized all the functions that defined the characteristics of the clock. I ended up with a module that enables you to create multiple instances of the clock, each with its own configuration, defined in the ‘face’ variable of the configuration object.

d3clock({
	target:'#sbb',
	face:'sbb',
	width:500,
	//date:'Mon May 25 2015 10:09:37',
	TZOffset:{
		hours:0
	}
});



You can get the code for the library here.

Mind you, this implementation has its differences with the SBB clock (perhaps that will spare me from a takedown notice?):

  • The SBB clock makes a 2 second pause at the end of each rotation. Yes, crazy, look.
  • The hands in the original clock are not rectangles, but very tall truncated triangles.

Having fun coding with p5.js

p5js
p5.js is an effort to port the ideas and concepts of the Processing programming language to JavaScript.

Even though there’s already processing.js —which transcodes Processing code into JavaScript—, p5.js is built with extensibility in mind, trough plugins, and instead of writing Processing code to be transcoded, you write pure JavaScript.

The other day I saw the p5.js launch presentation, and loved it. It made me do several double-takes as it shows wizardly things that you usually don’t see on video.

So I gave it a whirl. Following the very detailed examples on their site I was able to quickly put together a web toy that records audio through your microphone and then allows you to reproduce it, changing the volume and speed. Here it is:
(you have to accept the microphone prompt in your browser in order for this to work)

Here’s the code in github

It was quick, painless and fun. In fact, this was the most fun that I’ve had in a long while learning a new JavaScript library. The onboarding experience that these guys have in their website it’s absolutely great.

I’ve never learned Processing, but have seen some wicked visualizations done with it. Seems like the routines and the concepts in p5.js are very similar, and the first thing that came to mind when I dove into it was Logo, my first language. I think it’s the procedural, sequential nature of it. The rules are very clear, each instruction modifies the context, and there’s this pervasive idea that you’re drawing in a canvas object in a web page.

I bet p5.js would make for a great introduction to programming for kids, with the added benefit that, along the way, any beginner that starts with p5.js would be learning one of the most popular languages today. And having fun at the same time.

p5.js website

 



Clear Off the Table | Dark Horse Analytics

ClearOffTheTableMd

Following their great Data Looks Better Naked post, the clever guys at Dark Horse Analytics have created a guide on how to remove Chartjunk and create really clean and expressive tables.

The gif above pretty much sums it up, but go and read the full post.

 

Creating interactive visualizations of large datasets using JavaScript

Crossfilter is a JavaScript library initially designed by Square to explore large multivariate datasets in a web browser. It basically allows you to create sorted indexes and feed them to a charting library like D3, and enable the user to filter by clicking and dragging, even when sifting through 200.000 rows in a 5MB file:

Time of Day
Arrival Delay (min.)
Distance (mi.)
Date

(go ahead, you can play with it. Click and drag on any of the charts to perform a live filtering of the dataset)

The process to create these charts is relatively easy:
1. Load the data.
2. Define the dimensions with crossfilter.
3. Create the charts with D3.
4. Write the event code to respond to clicks and filters.

The main challenge of using crossfilter is that you have to spend quite some time fighting engaging D3 to make the charts respond to filter changes and user clicks. These charts have to be wired together, so when you click on one, the others respond to the action. The JavaScript code for the chart above is about 300 lines and was made by clever guys who work at Square.

There’s also the question of reusability. How much code would we have to write –and maintain– if we wanted to adapt any of these charts to another visualization?

A lot!

This is the main problem with using D3.js as a charting library and doing everything by hand. The development and testing of a single non-trivial dashboard could take weeks, if not months.

You know what would be ideal? To have a charting library that allowed us to use large datasets with crossfilter and, at the same time, enabled us to create reusable charts that we could easily plug in wherever we want.

That’s exactly what dc.js does. Here I’m loading the same 5MB, 200.000 records file, and dealing with it in only 121 lines of un-optimized JavaScript.

Time of Day

Arrival Delay (min.)

Distance (mi.)

Date

(click and drag on any of the charts to filter the data)

This is the same set of charts, but done in a much simpler, faster and expressive way.

Take a look at the samples they have in their site, like this interactive Twitter dashboard or this stock picker.

dc.js performs the dirty work of linking the charts together, so when we click on a chart, the other charts in the group respond automatically, without writing any additional code. Magic!






A reliable list of country codes

country-codes

Who knows how much time I’ve wasted over the years trying to find a reliable data source for country names, ISO codes, phone prefixes and currencies.

I have my own personal dysfunctional set of tables built manually from bits and pieces found online. But the other day I ran into this beauty: and updated ISO 3166 and ISO 4217 country and currency codes, with some FIFA and ITU codes thrown into the mix. The list is provided in CSV and JSON format and is now my one-stop solution for country codes.