Tom MacWright / @tmcw / tmcw
dev @MapBox
writing/hackin @macwright.org
want more words? here's an accompaniment
minute (keystrokes)
Not a chart library (though you can make charts with it)
Not a map library (though you can make maps with it)
Not a compatibility layer (it doesn't work with bad browsers)
Not about SVG or HTML or Canvas (though you can use it with them)
not an SVG abstraction layer
it doesn't have its own way of making a line or a circle. it makes you deal with svg elements as svg elements. plus, you can deal with HTML elements and Canvas elements!
d3.select('#foo')
.style('background', '#000')
.on('click', function() {})
.append('div');
$('#foo')
.css('background', '#000')
.click(function() {})
.append($('<div></div>'));
d3.json('foo.json',
function(err, data) { });
$.getJSON('foo.json',
function(data) { });
that's just the silly stuff, though
// a fully-featured jquery replacement
function $(x) {
return document.querySelectorAll(x);
}
// a fully-featured jquery replacement
$.ajax = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.onload = callback;
xhr.send();
}
let's get to the hard stuff, then
Let's review some Javascript (1x)
why did we learn that? because identifying objects is one of the biggest parts of the join
now let's understand the hardest part of d3 by building it from scratch.
you have the knowledge! time to d3.
d3.selectAll('div')
.data([1, 2, 3])
.enter()
.append('div')
.text(String);
// an empty selection.
// looking for instantiations of data
d3.selectAll('div')
// data, which would be bound to a
// selection
.data([1, 2, 3])
// for every time that we see data
// but we do not see an element
.enter()
// append an element
.append('div')
// and fill it with text
.text(String);
// and fill it with text
.text(String);
// wait what
// what's going on here?
.text(String);
d3.selectAll('div')
.data([1, 2, 3])
.enter()
.append('div')
.text(String);
// d3 has a few different
// functions that set stuff
.text()
.property()
.style()
.attr()
// each takes a function
.attr('foo', function() { })
// and that function gets data
// from your .data()
.attr('foo', function(d) {
return d.foo;
})
// like jQuery, you can chain these
blah
.attr('foo', 'bar')
.attr('boo', 'burr');
// like jQuery, you can use them
// to get an existing value
var fooValue = blah.attr('foo');
// if you provide a static argument,
// it becomes a functor
.attr('foo', 5)
// here's what a functor is
function functor(x) {
return function() {
return x;
};
}
we just used a closure.
don't know what a closure is?
bit.ly/js-closure-explain
// and what it does
var val = functor(10);
// val is now a function that
// always returns 10
assert.equal(val(), 10);
but what did you mean by .enter()?
d3 is all about enter, exit, and update
// this is an empty selection
var selection = d3.selectAll('div')
.data([1, 2, 3]);
// for each part of the data which
// is not joined to an element in
// the selection,
// add an element
selection
.enter()
.append('div');
// for each part of the selection
// that is no longer in the data,
// remove it
selection
.exit()
.remove();
// for each part of the selection,
// update some attribute
selection
.text(function(d) {
return d.bar;
});
so data is bound to the DOM
but what does that mean?
// WE NEED TO GO DEEPER
// WHAT IS REALLY HAPPENING
<div class='joined-elem'></div>
// a joined element like this has
// a __data__ property where
// WE KEEP THE DATA
we just awkwardly explained joins
read mike's explanations: bost.ocks.org/mike/join/ mbostock.github.com/d3/tutorial/circle.html
Joining data to elements is the trickiest part of d3. Here are some less-tricky transformations
d3.scale.linear()
// data comes in
.domain([0, 100])
// representation comes out
.range([0, 1]);
var projection = d3.geo.mercator();
// data goes in
// representation comes out
var px projection([lon, lat]);
Same rule as jQuery's reusing $blah = $('#blah')
var fooSelection = d3.selectAll('#foo');
// do not turn around and do
d3.selectAll('#foo')
// again
and they love math
var graph = new Rickshaw.Graph({
element: document.querySelector("#rick"),
renderer: 'bar',
series:[{
data:[{ x:0, y:40 }, { x:1, y:49 }],
color:'steelblue'
}, {
data:[{ x:0, y:20 }, { x:1, y:24 }],
color:'lightblue'
}]});
4: Postscript, Where to Go From Here
It is not about d3.
d3 is about it.
It's zany.