d3
- Created by Mike Bostock, who has lots of great examples
- Inherits lots of lessons from Prefuse (java), Flare (flash), and Protovis (javascript)
- Library for creating web-based visualizations
- Can be used with HTML, SVG, or Canvas
Declarative
- d3 is basically a DSL for binding data to the Document Object Model (DOM)
- Apply data-driven transformations to the document
- Tell d3 what you want done, not how to do it
- This is not like OpenGL or other graphics packages
-
Functions are everywhere in d3
Skeleton
What does this do?
console.log('append some text to the body of the page');
d3.select('body')
.append('text')
.text('d3 version ' + d3.version + ' is loaded.');
run
Selection
- Selectors are patterns to select items from the DOM
- Selections are a subclass of an array
- Actually, selections are arrays of arrays of elements: a selection is an array of groups, and each group is an array of elements
- d3 uses css3 selectors
- Selections are transient
-
d3.select(selector): Selects the first element that matches the specified selector string, returning a single-element selection
-
d3.selectAll(selector): Selects all elements that match the specified selector
read more about selections
Selector examples
What do these select?
d3.select('body')
d3.select('#anId')
d3.select(this)
d3.selectAll('.circles')
d3.selectAll('p')
d3.selectAll('div.content')
Selector examples
d3.select('body') // selects the entire, single body of the document
d3.select(this) // selects the referenced node in an event listener
d3.select('#anId') // selects the element with the id of 'anId'
d3.selectAll('.circles') // selects all elements with class 'circle'
d3.selectAll('p') // selects all paragraph elements on a page
d3.selectAll('div.content') // selects all divs with class 'content'
Dynamic properties
d3.selectAll("p")
.data([4, 6, 8, 10, 14, 16, 24, 42, 88])
.enter()
.append("p")
.style("font-size", function(d) { return d + "px"; })
.text(function(d, i) {
return 'Paragraph ' + i + ' is sized at ' + d + ' pixels.';
});
run
Functions are everywhere
- Almost all of the methods in d3 accept an anonymous function. This is a very common pattern:
someOperator(..., function(d, i) {return somethingToDoWithDatum;})
-
d refers to the current selected datum. i refers to the index of the datum
- This anonymous function is often called the accessor function, because it is often used to tell the operator how to access the data and what to do with it
Example accessor functions
What do these do?
something.attr('width', function(d, i) {
return w * i;
});
something.style('color', function(d, i) {
return i % 2 ? "#fff" : "#bbb";
});
something.text(function(d) {
return 'Name: ' + d.name + ', phone: ' + d.phone;
});
Data-join
- Data is bound to the DOM - this is called a data-join
-
data([someData]) returns three virtual selections: enter, update and exit
-
Enter: If there is no existing data, all data ends up as placeholder nodes in enter()
-
Update: The update selection contains existing elements, bound to data
-
Exit: Anything left over are in the exit selection for removal
General update pattern
var circle = svg.selectAll("circle")
.data(data);
circle.enter().append("circle")
.attr("r", 2.5);
circle
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
circle.exit().remove();
Enter, Update, and Exit
- If the new dataset is smaller than the old one, the surplus elements end up in the exit selection and get removed
- If the new dataset is larger, the surplus data ends up in the enter selection and new nodes are added
- If the new dataset is exactly the same size, then all the elements are simply updated with new positions, and no elements are added or removed
Now with transitions
var circle = svg.selectAll("circle")
.data(data);
circle.enter().append("circle")
.attr("r", 0)
.transition()
.attr("r", 2.5);
circle
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
circle.exit().transition()
.attr("r", 0)
.remove();
read more about data-joins
Using d3: the quick and dirty
Fire up a web server
- Using Python's built in web server
python -m SimpleHTTPServer 8000
# For Pythong 3+, use http.server instead
python -m http.server 8000
- Using nodejs, and a web server, such as http-server
npm install http-server -g
http-server -p 8000
Libraries on top of d3
-
nvd3 Reusable d3 components - Seems pretty nice. Weird licensing issues
-
dc D3 + Crossfilter – Seems like it does a lot
-
d3.chart Framework for reusable d3 charts – Nicely designed abstraction
Working with utility libs
-
Jquery DOM manipulation, Ajax, etc. - Used everywhere
-
Lodash Data manipulation - Nicer than using d3 sometimes for working with arrays, collections and objects (cf. underscore)
- That said, d3 does almost all of this...
Working with frameworks
-
Backbone MVC-ish - Low barrier to getting started, but will probably be looking elsewhere...
-
Angular HTML extension, data binding - It is probably awesome. Or just weird. See Brian Ford's post for working with Angular and d3.
-
Flight event-driven - Tries to make you write more modular and reusable code.