Upload
anton-katunin
View
32.424
Download
1
Embed Size (px)
Citation preview
D3 WORKSHOP
WEB STANDARDS
D3 provides transformation; no new representation.
MAPPING DATA TO ELEMENTS
Visualisation requires visual encoding: mapping data to elements.
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