D3.js workshop

Post on 08-May-2015

32.410 views 1 download

Transcript of D3.js workshop

D3 WORKSHOP

WEB STANDARDS

D3 provides transformation; no new representation.

MAPPING DATA TO ELEMENTS

Visualisation requires visual encoding: mapping data to elements.

NOTHING NEWD3 refers to

Data-Driven Documents

W3C Document Object Model.

D3 = STANDARDS

Learning D3 is largely learning web standards

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/

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

SVG

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

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

SVG != HTML

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

CSS

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

</style> <body> Hello, world!

body { background: steelblue; }

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

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

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

</script>

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

STARTING WITH D3

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

/* CSS */

/* JavaScript */

DEVELOPER TOOLS

DASHlatest version

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

SELECTORS

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">

SELECTORSJavascript

jQuery

D3

document.querySelectorAll("pre, code")

$('pre, code')

d3.selectAll("pre, code")

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");

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");

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!");

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

selection!

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

DATA

DATA ARE ARRAYSSelections are arraysData are arrays

Coincidence?

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} ];

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);

.DATA()Use data to create multiple elements.

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

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

Appending to the enter selection creates the missingelements.

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

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

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);

ENTER, UPDATE & EXITThinking with Joins

ENTERNew data, for which there were no existing elements.

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);

UPDATENew data that was joined successfully to an existing element.

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);

EXITExisting elements, for which there were no new data.

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

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

ENTER + UPDATEEntering nodes are added to update on append.

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

circle.exit().remove();

KEY FUNCTIONYou can control the join;

by default, the join is by index.

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} ];

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);

LOADING DATAD3 provides several convenience routines using

.

CSVJSON

XMLHttpRequest

D3 AND ARRAY

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

array. {filter,map,sort,…}

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

d3. {nest,keys,values,…}

API

SCALES

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"; }

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

linearsqrtpowlogquantizethresholdquantileidentity

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

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

constant.

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]);

INTERPOLATORSQuantitative scales support multiple interpolators.

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

OBJECT INTERPOLATIONjust to mention

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

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

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

COLOR SCALE

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

AXIS

AXISD3 provides convenient labeling for scales.

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; }

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]

TICK FORMATSd3.formatd3.time.format

MARKS/SHAPES

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

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 + ")");

SVG BASIC SHAPESrectcirclelinetext

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…">

PATH GENERATORSConfigurable functions for generating paths from data.

d3.svg.lined3.svg.area

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);

D3.SVG.AREACheck the docs

LINE INTERPOLATORSLine and area generators support multiple interpolation

modes.

Linear, Step and Basis Interpolation

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

d3.svg.arc

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);

LAYOUTS

LAYOUTS ARE DATALayouts are reusable algorithms that generate data, not

display.

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

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

D3.LAYOUT.TREEMAP

D3.LAYOUT.TREE

D3.LAYOUT.PACK

D3.LAYOUT.PARTITION

Layouts are configurable functions.

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

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);

D3.LAYOUT.FORCE

D3.LAYOUT.BUNDLE

D3.GEOM.VORONOI

D3.LAYOUT.CHORD

SUM UPSelectorsDataJoins (enter, update, exit)ScalesAxisShapesLayouts

NOW YOU KNOW D3JS

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

LET'S BUILD SOME STUFF