Web-Based Visualizations with D3.js

Web-Based Visualizations with D3.js

A5b424d4146905962a24acd6815aeb84?s=128

Stephen Thomas

November 19, 2012
Tweet

Transcript

  1. 1.

    stephen@sathomas.me icon-comment icon-comment-alt icon-comments icon-comments-alt icon-credit-card icon-dashboard icon-download icon-download-alt icon-edit

    icon-envelope icon-envelope-alt icon-key icon-leaf icon-legal icon-lemon icon-lock icon-unlock icon-magic icon-magnet icon-map-marker icon-minus icon-minus-sign icon-resize-horiz icon-resize-verti icon-retweet icon-road icon-rss icon-screenshot icon-search icon-share icon-share-alt icon-shopping-c http://speakerdeck.com/sathomas Web-Based Visualizations with D3.js Stephen Thomas
  2. 2.

    Why Are You Viewing This Presentation? Seriously, unless you’re stuck

    in a room forced to hear my voice, there are better alternatives available. You could start here1, with a workshop presented by Mike Bostock himself. 1http://bost.ocks.org/mike/d3/workshop/
  3. 3.

    Visualization: From Data I could tell you that in the

    War of 1812 Napoleon began his march on Moscow with an army of 422,000 men and ended his retreat with about 10,000 men. …
  4. 8.

    What D3.js Brings •Javascript library to help you create spectacular

    visualizations •With full interactivity using standard HTML/CSS/Javascript events •That can be automatically updated in real time as underlying data changes
  5. 9.

    D3.js is not Beta Many top notch organizations are actively

    using D3.js for their online content, e.g.: • New York Times: Four Ways to Slice Obama’s 2013 Budget Proposal • Le Monde: De Maastricht au traité budgétaire • New Scientist: The Changing Face of America
  6. 10.

    But Doesn’t It Have a Reputation? “Once you pass the

    learning curve…” “D3 has a steep learning curve…” “…it has a steep learning curve…” “There is a huge learning curve…” “…the learning curve was quite steep.” http://www.datameer.com/blog/uncategorized/whats-behind-our-business-infographics-designer-d3-js-of-course-2.html http://www.recursion.org/d3-for-mere-mortals/ http://www.visweek.org/visweek/2012/tutorial/visweek/introduction-data-visualization-web-d3js http://dyninc.github.com/lunch-and-learn/1202-d3js.html http://www.tips-for-excel.com/tag/learn-d3-js-book/
  7. 12.

    D3.js: Data Driven Documents •Javascript utilities that manage the association

    of data with DOM elements •Convenience functions for common, tedious tasks •Leaves it to you to design the best way to make the data understandable
  8. 13.

    D3.js as Assembly Line Data (JSON, CSV, XML, …) plus

    elements (HTML, SVG, …) Photograph source: http://www.flickr.com/photos/lac-bac/4679195538/ Office national du film du Canada. Photothèque. Bibliothèque et Archives Canada
  9. 14.

    Assembly Plant: HTML Document <!DOCTYPE html> <html lang="en"> <head> <meta

    charset="utf-8"> <title></title> </head> <body> </body> </html>
  10. 15.

    Assembly Line Part A: Data d3.json("numbers.json", function(numbers) { // numbers

    has the values we want to “visualize” // numbers[i].value is the value itself // numbers[i].key is a unique key for each });
  11. 16.

    Assembly Line Part A: Data d3.json("numbers.json", function(numbers) { // numbers

    has the values we want to “visualize” // numbers[i].value is the value itself // numbers[i].key is a unique key for each }); d3.json( ) is part of the D3 library. It retrieves JSON-formatted data from a URL, in this case the URL is numbers.json.
  12. 17.

    Assembly Line Part A: Data d3.json("numbers.json", function(numbers) { // numbers

    has the values we want to “visualize” // numbers[i].value is the value itself // numbers[i].key is a unique key for each }); When the data is available, D3 calls the indicated (callback) function; the parameter is the data returned from the URL.
  13. 18.

    Assembly Line Part B: Elements d3.json("numbers.json", function(numbers) { // numbers

    has the values we want to “visualize” // numbers[i].value is the value itself // numbers[i].key is a unique key for each // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers); });
  14. 19.

    Assembly Line Part B: Elements d3.json("numbers.json", function(numbers) { // numbers

    has the values we want to “visualize” // numbers[i].value is the value itself // numbers[i].key is a unique key for each // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers); }); We tell D3 we want to use <p> elements within the <body> tag for our data values. (The function names will make sense in a bit.)
  15. 20.

    Assembly Line Part B: Elements d3.json("numbers.json", function(numbers) { // numbers

    has the values we want to “visualize” // numbers[i].value is the value itself // numbers[i].key is a unique key for each // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers); }); Create a one-to-one correspondence between data values and <p> elements.
  16. 21.

    Optional: “Serial Numbers” for the Data d3.json("numbers.json", function(numbers) { //

    numbers has the values we want to “visualize” // numbers[i].value is the value itself // numbers[i].key is a unique key for each // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); });
  17. 22.

    Optional: “Serial Numbers” for the Data d3.json("numbers.json", function(numbers) { //

    numbers has the values we want to “visualize” // numbers[i].value is the value itself // numbers[i].key is a unique key for each // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); }); The call to D3’s data( ) takes an optional second parameter. That parameter provides a key, or unique identifier, for the given data value.
  18. 23.

    Optional: “Serial Numbers” for the Data d3.json("numbers.json", function(numbers) { //

    numbers has the values we want to “visualize” // numbers[i].value is the value itself // numbers[i].key is a unique key for each // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); }); This function is important if we need D3 to distinguish different data values from each other. (By default, D3 uses their index in the data set.)
  19. 24.

    Assembly Instructions d3.json("numbers.json", function(numbers) { // numbers has the values

    we want to “visualize” // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); // what to do when data becomes available ptags.enter().append("p") .text(function(d) { return "Value: " + d.value; }); });
  20. 25.

    Assembly Instructions d3.json("numbers.json", function(numbers) { // numbers has the values

    we want to “visualize” // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); // what to do when data becomes available ptags.enter().append("p") .text(function(d) { return "Value: " + d.value; }); }); If there isn’t a <p> tag for a particular data value, ...
  21. 26.

    Assembly Instructions d3.json("numbers.json", function(numbers) { // numbers has the values

    we want to “visualize” // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); // what to do when data becomes available ptags.enter().append("p") .text(function(d) { return "Value: " + d.value; }); }); … create a new <p> tag for the data value, ...
  22. 27.

    Assembly Instructions d3.json("numbers.json", function(numbers) { // numbers has the values

    we want to “visualize” // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); // what to do when data becomes available ptags.enter().append("p") .text(function(d) { return "Value: " + d.value; }); }); … and set the text contents of the newly created <p> tag to show the value of the data.
  23. 28.

    Assembly Instructions d3.json("numbers.json", function(numbers) { // numbers has the values

    we want to “visualize” // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); // what to do when data becomes available ptags.enter().append("p") .text(function(d) { return "Value: " + d.value; }); }); Note that D3’s append( ) returns the newly created element, not the container to which it was appended.
  24. 29.

    Assembly Instructions d3.json("numbers.json", function(numbers) { // numbers has the values

    we want to “visualize” // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); // what to do when data becomes available ptags.enter().append("p") .text(function(d) { return "Value: " + d.value; }); }); This return value is different from the jQuery append( ) function, so be careful when chaining methods.
  25. 30.

    Waste Removal d3.json("numbers.json", function(numbers) { // numbers has the values

    we want to “visualize” // ... // what to do if data disappears ptags.exit().remove(); });
  26. 31.

    Waste Removal d3.json("numbers.json", function(numbers) { // numbers has the values

    we want to “visualize” // ... // what to do if data disappears ptags.exit().remove(); }); If there isn’t a data value (any more) for a particular <p> tag, ...
  27. 32.

    Waste Removal d3.json("numbers.json", function(numbers) { // numbers has the values

    we want to “visualize” // ... // what to do if data disappears ptags.exit().remove(); }); then just remove the <p> tag from the document.
  28. 33.

    Start the Day Shift function update() { d3.json("numbers.json", function(numbers) {

    // numbers has the values we want to “visualize” // ... }); } setInterval(update, 5000);
  29. 34.

    Start the Day Shift function update() { d3.json("numbers.json", function(numbers) {

    // numbers has the values we want to “visualize” // ... }); } setInterval(update, 5000); Put all the previous code in a function, ...
  30. 35.

    Start the Day Shift function update() { d3.json("numbers.json", function(numbers) {

    // numbers has the values we want to “visualize” // ... }); } setInterval(update, 5000); and call that function periodically.
  31. 36.

    And the Night Shift function update() { d3.json("numbers.json", function(numbers) {

    // numbers has the values we want to “visualize” // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); // ... }); }
  32. 37.

    And the Night Shift function update() { d3.json("numbers.json", function(numbers) {

    // numbers has the values we want to “visualize” // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); // ... }); } On subsequent passes, D3 will automatically identify the <p> tags that are already present in the HTML document.
  33. 38.

    And the Night Shift function update() { d3.json("numbers.json", function(numbers) {

    // numbers has the values we want to “visualize” // and we want to associate each point with a <p> var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); // ... }); } And D3 will automatically match the (possibly) updated data set to the pre- existing <p> elements.
  34. 39.

    And the Night Shift function update() { d3.json("numbers.json", function(numbers) {

    var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); ptags.enter().append("p") .text(function(d) { return "Value: " + d.value; }); }); } If there isn’t a <p> tag for a particular data value, create a new <p> tag for the data value.
  35. 40.

    And the Night Shift function update() { d3.json("numbers.json", function(numbers) {

    var ptags = d3.select("body").selectAll("p") .data(numbers, function(d) { return d.key; }); ptags.enter().append("p") .text(function(d) { return "Value: " + d.value; }); ptags.exit().remove(); }); } If there isn’t a data value (any more) for a particular <p> tag, then just remove the <p> tag from the document.
  36. 41.

    The Key Concept: D3.js as Assembly Line •D3 automatically keeps

    track of data values and associated HTML (or SVG) elements. •As the data set changes, D3 identifies elements that need to be created and elements that are no longer needed. •All you have to do is tell it what to do with those elements.
  37. 42.

    The Power of D3.js •You can do anything you want

    with the HTML or SVG elements; after all, they’re standard HTML or SVG. (Style with CSS, make interactive with javascript, …) •You can control what happens when elements are added or removed. (Animations, anyone?) •But that seems like a lot of work...
  38. 43.

    Need Help with that Work? D3.js as Toolkit •Transitions, Arrays,

    Colors, Scales, Time •Scalable Vector Graphics (shapes, axes, controls) •Layouts (chords, clusters, force, hierarchy, histogram, pack, partition, pie, stack, tree, treemap) •Geography (paths, projections)