D3.js workshop

105
D3 WORKSHOP

Transcript of D3.js workshop

Page 1: D3.js workshop

D3 WORKSHOP

Page 2: D3.js workshop

WEB STANDARDS

D3 provides transformation; no new representation.

Page 3: D3.js workshop

MAPPING DATA TO ELEMENTS

Visualisation requires visual encoding: mapping data to elements.

Page 4: D3.js workshop

NOTHING NEWD3 refers to

Data-Driven Documents

W3C Document Object Model.

Page 5: D3.js workshop

D3 = STANDARDS

Learning D3 is largely learning web standards

Page 6: D3.js workshop

HTMLHTML5 Spec http://www.w3.org/TR/html5/HTML5 for Developers http://developers.whatwg.org/MDN https://developer.mozilla.org/en/HTMLDive Into HTML5 http://diveintohtml5.info/

Page 7: D3.js workshop

HTML 5<!DOCTYPE html><meta charset="utf-8"><body>Hello,world!

Page 8: D3.js workshop

SVG

SVG Spechttp://www.w3.org/TR/SVG/MDNhttps://developer.mozilla.org/en/SVGD3 API Referencehttps://github.com/mbostock/d3/wiki/SVG-Shapes

Page 9: D3.js workshop

SVG <!DOCTYPE html> <meta charset="utf-8"> <svg width="960" height="500"> <text y="12"> Hello, world! </text> </svg>

Page 10: D3.js workshop

SVG != HTML

Page 11: D3.js workshop

CSSCSS Spechttp://www.w3.org/TR/CSS2/Selectors Spechttp://www.w3.org/TR/selectors/

Page 12: D3.js workshop

CSS

<!DOCTYPE html> <meta charset="utf-8"> <style>

</style> <body> Hello, world!

body { background: steelblue; }

Page 13: D3.js workshop

JAVASCRIPTMDNhttps://developer.mozilla.org/en/JavaScript

Douglas Crockford’s JavaScript: The Good Partshttp://shop.oreilly.com/product/9780596517748.dohttp://javascript.crockford.com/

Page 14: D3.js workshop

JAVASCRIPT <!DOCTYPE html> <meta charset="utf-8"> <body> <script>

</script>

console.log("Hello, world!");

Page 15: D3.js workshop

STARTING WITH D3

Page 16: D3.js workshop

START SMALL <!DOCTYPE html> <meta charset="utf-8"> <style> </style> <body> <script src="d3.v2.js"></script> <script> </script>

/* CSS */

/* JavaScript */

Page 17: D3.js workshop

DEVELOPER TOOLS

Page 18: D3.js workshop

DASHlatest version

Page 19: D3.js workshop
Page 20: D3.js workshop

D3 RESOURCESD3 API Referencehttps://github.com/mbostock/d3/wiki/API-ReferenceD3 Wikihttps://github.com/mbostock/d3/wikiD3 Grouphttps://groups.google.com/group/d3-jsD3 Stack Overflowhttp://stackoverflow.com/questions/tagged/d3.js

Page 21: D3.js workshop

SELECTORS

Page 22: D3.js workshop

CSS SELECTORS

CSS style selectors

pre, code { font-family: "Menlo", monospace; font-size: 48px; }

#foo // <any id="foo"> foo // <foo> .foo // <any class="foo"> [foo=bar] // <any foo="bar"> foo bar // <foo><bar></foo>

foo.bar // <foo class="bar"> foo#bar // <foo id="bar">

Page 23: D3.js workshop

SELECTORSJavascript

jQuery

D3

document.querySelectorAll("pre, code")

$('pre, code')

d3.selectAll("pre, code")

Page 24: D3.js workshop

SELECTIONS ARE ARRAYS // select all <circle> elements var circle = d3.selectAll("circle");

// set some attributes and styles circle.attr("cx", 20); circle.attr("cy", 12); circle.attr("r", 24); circle.style("fill", "red");

Page 25: D3.js workshop

METHOD CHAINING // select all <circle> elements // and set some attributes and styles d3.selectAll("circle") .attr("cx", 20) .attr("cy", 12) .attr("r", 24) .style("fill", "red");

Page 26: D3.js workshop

SELECTION.APPENDSingle

Collection

// select the <body> element var body = d3.select("body");

// add an <h1> element var h1 = body.append("h1"); h1.text("Hello!");

// select all <section> elements var section = d3.selectAll("section");

// add an <h1> element to each var h1 = section.append("h1"); h1.text("Hello!");

Page 27: D3.js workshop

WARNING!!Use caution with method chaining: append returns a new

selection!

var h1 = d3.selectAll("section") .style("background", "steelblue") .append("h1") .text("Hello!");

Page 28: D3.js workshop

DATA

Page 29: D3.js workshop

DATA ARE ARRAYSSelections are arraysData are arrays

Coincidence?

Page 30: D3.js workshop

DATANumbers

Objects

// A bar chart, perhaps? var data = [1, 1, 2, 3, 5, 8];

// A scatterplot, perhaps? var data = [ {x: 10.0, y: 9.14}, {x: 8.0, y: 8.14}, {x: 13.0, y: 8.74}, {x: 9.0, y: 8.77}, {x: 11.0, y: 9.26} ];

Page 31: D3.js workshop

DATA TO ELEMENTSUse data to create multiple elements.

We want the selection “circle” to correspond to data.

svg.selectAll("circle") .data(data) .enter().append("circle") .attr("cx", x) .attr("cy", y) .attr("r", 2.5);

Page 32: D3.js workshop

.DATA()Use data to create multiple elements.

The data method computes the join, defining enter and exit.

var circle = svg.selectAll("circle") .data(data);

Page 33: D3.js workshop

Appending to the enter selection creates the missingelements.

var circle = svg.selectAll("circle") .data(data);

circle.enter().append("circle");

Page 34: D3.js workshop

The new elements are bound to data, so we can computeattributes.

function x(d) { return d.x; } function y(d) { return d.y; }

var circle = svg.selectAll("circle") .data(data);

circle.enter().append("circle") .attr("cx", x) .attr("cy", y) .attr("r", 2.5);

Page 35: D3.js workshop

ENTER, UPDATE & EXITThinking with Joins

Page 36: D3.js workshop

ENTERNew data, for which there were no existing elements.

Page 37: D3.js workshop

When initializing, you might ignore update and exit.

var circle = svg.selectAll("circle") .data(data) .enter().append("circle") .attr("cx", x) .attr("cy", y) .attr("r", 2.5);

Page 38: D3.js workshop

UPDATENew data that was joined successfully to an existing element.

Page 39: D3.js workshop

UPDATEWhen updating, you might ignore enter and exit.

var circle = svg.selectAll("circle") .data(data) .attr("cx", x) .attr("cy", y) .attr("r", 2.5);

Page 40: D3.js workshop

EXITExisting elements, for which there were no new data.

Page 41: D3.js workshop

EXIT var circle = svg.selectAll("circle") .data(data);

circle.enter().append("circle") .attr("cx", x) .attr("cy", y) .attr("r", 2.5);

Page 42: D3.js workshop

ENTER + UPDATEEntering nodes are added to update on append.

Page 43: D3.js workshop

ENTER + UPDATE var circle = svg.selectAll("circle") .data(data);

circle.exit().remove();

Page 44: D3.js workshop

KEY FUNCTIONYou can control the join;

by default, the join is by index.

Page 45: D3.js workshop

If needed, data should have a unique key for joining.

// A scatterplot, perhaps? var data = [ {name: "Alice", x: 10.0, y: 9.14}, {name: "Bob", x: 8.0, y: 8.14}, {name: "Carol", x: 13.0, y: 8.74}, {name: "Dave", x: 9.0, y: 8.77}, {name: "Edith", x: 11.0, y: 9.26} ];

Page 46: D3.js workshop

The key function returns a unique string for each datum.

function key(d) { return d.name; }

var circle = svg.selectAll("circle") .data(data, key) .attr("cx", x) .attr("cy", y) .attr("r", 2.5);

Page 47: D3.js workshop

LOADING DATAD3 provides several convenience routines using

.

CSVJSON

XMLHttpRequest

Page 48: D3.js workshop

D3 AND ARRAY

Page 49: D3.js workshop

D3 AND ARRAYJavaScript has a number of useful built-in array methods.

array. {filter,map,sort,…}

Page 50: D3.js workshop

D3 also has a variety of data-transform methods; explore the.

d3. {nest,keys,values,…}

API

Page 51: D3.js workshop

SCALES

Page 52: D3.js workshop

DOMAIN => RANGEScales are functions that map from data-space to visual-

space.

Scales are convenient but optional; you can roll your own.

function x(d) { return d * 42 + "px"; }

Page 53: D3.js workshop

QUANTITATIVE SCALESMap a continuous (numeric) domain to a continuous range.

linearsqrtpowlogquantizethresholdquantileidentity

Page 54: D3.js workshop

var x = d3.scale.linear() .domain([12, 24]) .range([0, 720]);

x(16); // 240

var x = d3.scale.sqrt() .domain([12, 24]) .range([0, 720]);

x(16); // 268.9056992603583

var x = d3.scale.log() .domain([12, 24]) .range([0, 720]);

x(16); // 298.82699948076737

Page 55: D3.js workshop

DOMAINS & RANGESTypically, domains are derived from data while ranges are

constant.

Page 56: D3.js workshop

var x = d3.scale.linear() .domain([0, d3.max(numbers)]) .range([0, 720]);

var x = d3.scale.log() .domain(d3.extent(numbers)) .range([0, 720]);

function value(d) { return d.value; }

var x = d3.scale.log() .domain(d3.extent(objects, value)) .range([0, 720]);

Page 57: D3.js workshop

INTERPOLATORSQuantitative scales support multiple interpolators.

Page 58: D3.js workshop

var x = d3.scale.linear() .domain([12, 24]) .range(["steelblue", "brown"]);

x(16); // #666586

var x = d3.scale.linear() .domain([12, 24]) .range(["0px", "720px"]);

x(16); // 240px

var x = d3.scale.linear() .domain([12, 24]) .range(["steelblue", "brown"]) .interpolate(d3.interpolateHsl);

x(16); // #3cb05f

Page 59: D3.js workshop

OBJECT INTERPOLATIONjust to mention

Page 60: D3.js workshop

DIVERGING SCALESSometimes, you want a compound (“polylinear”) scale.

var x = d3.scale.linear() .domain([-10, 0, 100]) .range(["red", "white", "green"]);

x(-5); // #ff8080 x(50); // #80c080

Page 61: D3.js workshop

ORDINAL SCALESAn ordinal scale is essentially an explicit mapping.

var x = d3.scale.ordinal() .domain(["A", "B", "C", "D"]) .range([0, 10, 20, 30]);

x("B"); // 10

Page 62: D3.js workshop

var x = d3.scale.category20() .domain(["A", "B", "C", "D"]);

x("B"); // #aec7e8

var x = d3.scale.category20() .domain(["A", "B", "C", "D"]);

x("E"); // #2ca02c x("E"); // #2ca02c x.domain(); // A, B, C, D, E

Page 63: D3.js workshop

COLOR SCALE

Page 64: D3.js workshop

Ordinal ranges can be derived from continuous ranges.

var x = d3.scale.ordinal() .domain(["A", "B", "C", "D"]) .rangePoints([0, 720]);

x("B"); // 240

var x = d3.scale.ordinal() .domain(["A", "B", "C", "D"]) .rangeRoundBands([0, 720], .2);

x("B"); // 206, bar position x.rangeBand(); // 137, bar width

Page 65: D3.js workshop

AXIS

Page 66: D3.js workshop

AXISD3 provides convenient labeling for scales.

Page 67: D3.js workshop

Create

Render

Style

var yAxis = d3.svg.axis() .scale(y) .orient("left");

svg.append("g") .attr("class", "y axis") .call(yAxis);

.axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; }

Page 68: D3.js workshop
Page 69: D3.js workshop

TICKSQuantitative scales can be queried for “human-readable”

values.

The requested count is only a hint (for better or worse).

var x = d3.scale.linear() .domain([12, 24]) .range([0, 720]);

x.ticks(5); // [12, 14, 16, 18, 20, 22, 24]

Page 70: D3.js workshop

TICK FORMATSd3.formatd3.time.format

Page 71: D3.js workshop

MARKS/SHAPES

Page 72: D3.js workshop

SVG COORDINATESAbsolute positioning; the origin ⟨0,0⟩ is the top-left corner!

Page 73: D3.js workshop

Use margins for decorative elements, such as axes.

var svg = d3.select("body").append("svg") .attr("width", outerWidth) .attr("height", outerHeight);

var g = svg.append("g") .attr("transform", "translate(" + marginLeft + "," + marginTop + ")");

Page 74: D3.js workshop

SVG BASIC SHAPESrectcirclelinetext

Page 75: D3.js workshop

SVG PATHS <path d="M152.64962091501462,320.5600780855698L133.88913955606318,325.4363177123538L134.96890954443046,330.37917634921996L131.19348249532786,331.158393614812L98.56681109628815,335.53933807857004L91.14450799488135,333.79662025279L72.1880101321918,333.74733970068166L69.51723455785742,332.8569681440152L62.37313911354066,333.2100666843387L62.248334309137434,335.3677272708405L58.843440998888326,335.0574959605036L53.97667317214221,331.36075125633175L56.30952738118711,325.9417994311851L63.80207296237137,326.0219658098969L68.37010032001055,321.68160223702955L68.82177412097933,318.08112591435287L73.34…">

Page 76: D3.js workshop

PATH GENERATORSConfigurable functions for generating paths from data.

d3.svg.lined3.svg.area

Page 77: D3.js workshop

D3.SVG.LINECreate

Render

var x = d3.scale.linear(), y = d3.scale.linear();

var line = d3.svg.line() .x(function(d) { return x(d.x); }) .y(function(d) { return y(d.y); });

svg.append("path") .datum(objects) .attr("class", "line") .attr("d", line);

Page 78: D3.js workshop

D3.SVG.AREACheck the docs

Page 79: D3.js workshop

LINE INTERPOLATORSLine and area generators support multiple interpolation

modes.

Linear, Step and Basis Interpolation

Page 80: D3.js workshop

RADIAL AREAS & LINESSimilar to d3.svg.{area,line}, except in polar coordinates.

d3.svg.arc

Page 81: D3.js workshop

D3.SVG.ARC var myExampleArc = { "innerRadius": 0, "outerRadius": 360, "startAngle": 0, // 12 o'clock "endAngle": 1.2 // radians };

var arc = d3.svg.arc() .innerRadius(0) .outerRadius(360);

// construct a default pie layout var pie = d3.layout.pie(); // derive data to feed to d3.svg.arc var myArcs = pie(numbers);

var path = svg.selectAll("path") .data(myArcs) .enter().append("path") .attr("d", arc);

Page 82: D3.js workshop
Page 83: D3.js workshop

LAYOUTS

Page 84: D3.js workshop

LAYOUTS ARE DATALayouts are reusable algorithms that generate data, not

display.

Page 85: D3.js workshop

LAYOUTS ARE VARIEDEach layout is different. Most are stateless, but not all.

Page 86: D3.js workshop

HIERARCHICAL LAYOUTSThere are lots of ways to visualize hierarchical data!

d3.layout.treemapd3.layout.treed3.layout.packd3.layout.partitiond3.layout.forced3.layout.bundled3.geom.voronoid3.geom.chord

Page 87: D3.js workshop

D3.LAYOUT.TREEMAP

Page 88: D3.js workshop

D3.LAYOUT.TREE

Page 89: D3.js workshop
Page 90: D3.js workshop

D3.LAYOUT.PACK

Page 91: D3.js workshop
Page 92: D3.js workshop

D3.LAYOUT.PARTITION

Page 93: D3.js workshop

Layouts are configurable functions.

var treemap = d3.layout.treemap() .padding(4) .size([width, height]);

Page 94: D3.js workshop

function x(d) { return d.x; } function y(d) { return d.y; } function dx(d) { return d.dx; } function dy(d) { return d.dy; }

svg.selectAll(".cell") .data(treemap.nodes(root)) .enter().append("rect") .attr("class", "cell") .attr("x", x) .attr("y", y) .attr("width", dx) .attr("height", dy);

Page 95: D3.js workshop

D3.LAYOUT.FORCE

Page 96: D3.js workshop

D3.LAYOUT.BUNDLE

Page 97: D3.js workshop
Page 98: D3.js workshop

D3.GEOM.VORONOI

Page 99: D3.js workshop
Page 100: D3.js workshop

D3.LAYOUT.CHORD

Page 101: D3.js workshop
Page 102: D3.js workshop

SUM UPSelectorsDataJoins (enter, update, exit)ScalesAxisShapesLayouts

Page 103: D3.js workshop

NOW YOU KNOW D3JS

Page 104: D3.js workshop

REFERENCEShttp://bost.ocks.org/mike/d3/workshop/

Page 105: D3.js workshop

LET'S BUILD SOME STUFF