D3 workshop

82
D3 WORKSHOP

description

D3 workshop conducted by Kiryl Verkhovin on Rolling Scopes meet up series.

Transcript of D3 workshop

Page 1: D3 workshop

D3 WORKSHOP

Page 2: D3 workshop

DATADRIVEN

DOCUMENTS

Page 3: D3 workshop

“D3 is not a compatibility layer,so if your browser doesn't support

standards, you're out of luck.Sorry!”

Page 4: D3 workshop

CREATE YOUR OWN VISUALIZATIONS

Page 5: D3 workshop

D3 IS NOT A CHARTING LIBRARYFor basic visualizations like "bar chart" use:

highchartsjqPlotnvd3...

Page 6: D3 workshop

SOURCE OF INSPIRATION

bl.ock.org

Page 7: D3 workshop

COLLISION DETECTION

see details

Page 8: D3 workshop

CHORD DIAGRAM

0k

5k

10k

15k

20k

25k

0k

5k

10k

15k20k

0k

5k

10k

15k

20k

25k

30k

35k

40k0k

5k

see details

Page 9: D3 workshop

FLEXIBLE TRANSITIONSAAPL

AMZN

IBM

MSFT

see details

Page 10: D3 workshop

COOL... BUTI STILL WANNA BAR CHART!

Page 11: D3 workshop

DATA

var data = [3, 5, 1, 7, 9];

USAGE

barChart(data);

Page 12: D3 workshop

SIMPLE BAR CHART

Page 13: D3 workshop

CREATE HOST PAGE

<!DOCTYPE html><html><head> <title>Bar chart</title> <style type="text/css"> div { height: 100px; background-color: green; margin-bottom: 10px;

color: white; line-height: 100px; font-size: 72px; text-align: right; padding-right: 10px; } </style></head><body></body><script src="../lib/d3.js" charset="utf-8"></script><script>window.data = [3, 5, 1, 7, 9]</script><script src="bar.live.js"></script></html>

Page 14: D3 workshop

NO D3

data.forEach(function (d) { var bar = document.createElement('div'); document.body.appendChild(bar); bar.style.setProperty('width', d * 100 + 'px'); bar.innerText = d;});

Page 15: D3 workshop

MIN D3

data.forEach(function (d) { d3.select('body').append('div') .style('width', d * 100 + 'px') .text(d);});

Page 16: D3 workshop

MAX D3

Page 17: D3 workshop

CREATE 3 DIVS

var body = d3.select('body');

body.append('div');body.append('div');body.append('div');

Page 18: D3 workshop

MODIFY DIVSfunction barChart() { body.selectAll('div') .style( 'background-color', 'blue') .text( 'Hello');}

Page 19: D3 workshop

DATA JOIN

//JOINvar binding = body.selectAll('div') .data(data);

binding.style('background-color', 'blue') .style('width', function (d) { return d * 50 + 'px'; }) .text(function (d) { return d; });

Page 20: D3 workshop

ENTER

//JOINvar binding = body.selectAll('div') .data(data);

//ENTERbinding.enter().append('div');

Page 21: D3 workshop

UPDATE + ENTER

//JOINvar binding = body.selectAll('div') .data(data);

//UPDATEbinding.style('background-color', 'blue')

//ENTERbinding.enter().append('div');

//ENTER + UPDATEbinding.style('width', function (d) { return d * 50 + 'px'; }) .text(function (d) { return d; });

Page 22: D3 workshop

EXIT

//JOINvar binding = body.selectAll('div') .data(data);

...

//EXITbinding.exit().remove();

Page 23: D3 workshop

GENERAL UPDATE PATTERNfunction barChart(data) { //JOIN var binding = body.selectAll('div') .data(data);

//UPDATE binding.style('background-color', 'blue');

//ENTER binding.enter().append('div');

//UPDATE + ENTER binding.style('width', function (d) { return d * 50 + 'px'; }) .text(function (d) { return d; });

//EXIT binding.exit().style('background-color', 'red').remove();}

Page 24: D3 workshop

MORE ABOUT SELECTIONS AND JOINSThree Little CirclesThinking with JoinsHow Selections Work

Page 25: D3 workshop

SCALESScales are functions that map from an input domain to an output

range.

learn more

Page 26: D3 workshop

SCALES

var scale = d3.scale.linear() .domain([20, 80]) .range([0, 120]);

scale(50); // return 60

Page 27: D3 workshop

SCALE BAR CHART

var scale = d3.scale.linear() .domain([0, d3.max(data)]) // -> in elephants .range([0, document.body.clientWidth]); // -> in px

...

//UPDATE + ENTERbinding.style('width', function (d) { return scale(d) + 'px'; }) .text(function (d) { return d; });

Page 28: D3 workshop

TRANSITIONSINTERPOLATE VALUES OVER TIME

numberscolorsgeometric transformsstrings with embedded numbers (e.g., "96px")

learn more

Page 29: D3 workshop

SVG <CIRCLE>

<svg width="800" height="800"> <circle cx="400" cy="400" r="200" fill="blue"></circle></svg>

Page 30: D3 workshop

MAKE CIRCLE ALIVE

var state1 = { r: 100, fill: 'red', cx: 200, cy: 200, opacity: 0.5 };var state2 = { r: 300, fill: 'blue', cx: 400, cy: 400, opacity: 1 };var circle = d3.select('circle');

function applyState(state) { circle.transition() .duration(2500) .ease('elastic') .attr('r', state.r) .attr('fill', state.fill) .attr('cx', state.cx) .attr('cy', state.cy) .style('opacity', state.opacity);}

Page 31: D3 workshop

TRANSITION DEMO

Page 32: D3 workshop

LET'S APPLY IT TO BAR CHART

//ENTERbars.enter().append('div') .style('width', 0);

//ENTER + UPDATEbars.text(function (d) { return d; }) .transition() .style('width', function (d) { return scale(d) + 'px'; });

Page 33: D3 workshop

BREAK

Page 34: D3 workshop

DONUT CHART

Page 35: D3 workshop

SVG <PATH>

<svg width="190px" height="160px"> <path d="M10 80 Q 52.5 10, 95 80 T 180 80" stroke="black" fill="transparent"/></svg>

Page 36: D3 workshop

SVG <G>The g element is a container used to group objects.

Transformations applied to the g element are performed on all ofits child elements.

<svg width="250" height="100"> <circle cx="50" cy="50" r="45" /> <g stroke="green" fill="white" transform="translate(90, 0)"> <circle cx="50" cy="50" r="45" /> <circle cx="80" cy="50" r="45" /> </g></svg>

Page 37: D3 workshop

D3 LAYOUTSLayouts are reusable algorithms that generate data, not display.

see more

Page 42: D3 workshop

AND SOME MORE...

Page 43: D3 workshop

PIE LAYOUT

var pie = d3.layout.pie();

pie([20, 50, 100]);

/* result ->[ {"data":20,"value":20,"startAngle":5.54,"endAngle":6.28}, {"data":50,"value":50,"startAngle":3.71,"endAngle":5.54}, {"data":100,"value":100,"startAngle":0,"endAngle":3.71}]*/

Page 44: D3 workshop

ARC GENERATORvar arc = d3.svg.arc().innerRadius(r / 2).outerRadius(r);

arc({"startAngle":0,"endAngle":3.71});//-> "M0,-20A20,20 0 1,1 -10.76581016580034,16.85518707917385L-5.38290508290017,8.427593539586924A10,10 0 1,0 0,-10Z"

Page 45: D3 workshop

DEMO DONUT CHART V.1

Page 46: D3 workshop

ADD COLORSvar color = d3.scale.category10();

color(0);//-> "#1f77b4"

Page 47: D3 workshop

DEMO DONUT CHART V.2

Page 48: D3 workshop

ADD LABELS//translate to arc's centertext.attr('transform', function (d) { return 'translate(' + arc.centroid(d) + ')';})//center horizontally.attr('text-anchor', 'middle')//center vertically.attr('dy', '.35em')

Page 49: D3 workshop

DEMO DONUT CHART V.3

Page 50: D3 workshop

ARC TWEEN

see details

Page 51: D3 workshop

DEMO DONUT CHART V.4

Page 52: D3 workshop

BREAK

Page 53: D3 workshop

Original:

LET'S DRAW BELARUS

Let’s Make a Map

Page 54: D3 workshop

FINDING DATA SOURCESGovernment ;)GeoCommonsNaturalEarthData

Page 56: D3 workshop

ESRI SHAPEFILEPopular geospatial vector data format for geographic

information system software.

BinaryBunch of files (*.dbf, *.shp, ...)Not in JSON :)

Page 57: D3 workshop

GEOJSON{ "type": "FeatureCollection", "features": [{ "type": "Feature", "properties": {}, "geometry": { "type": "Polygon", "coordinates": [ [ [27.4603271484375, 53.92698552779884], [27.5537109375, 53.97870483500941], [27.740478515625, 53.930219863940025], [27.696533203125, 53.81038242731128], [27.4932861328125, 53.80713881129993], [27.4603271484375, 53.92698552779884] ] ] } }]}

Learn more...

Page 58: D3 workshop

TOPOJSONExtension of GeoJSON that encodes topology.

Join shared lines into arcs.

BENEFITS:

smaller size (80% smaller)automatic mesh generation

Page 59: D3 workshop

TOPOJSON{ "type": "Topology", "objects": { "collection": { "type": "GeometryCollection", "geometries": [{ "type": "Polygon", "arcs": [ [0] ] }] } }, "arcs": [ [ [0, 6985], [3333, 3014], [6666, -2826], [-1568, -6984], [-7255, -189], [-1176, 6985] ] ], "transform": { "scale": [0.000028017938512601262, 0.00001715831820276837], "translate": [27.4603271484375, 53.80713881129993] }, "bbox": [27.4603271484375, 53.80713881129993, 27.740478515625, 53.97870483500941]

Page 60: D3 workshop

INSTALLING TOOLSGDAL/OGR2OGR

TOPOJSON

HTTP SERVER

Page 61: D3 workshop

GDAL/OGR2OGRUBUNTU

add-apt-repository ppa:ubuntugis/ppaapt-get updateapt-get install gdal-bin

Page 62: D3 workshop

GDAL/OGR2OGRMAC

brew install gdal

Page 63: D3 workshop

GDAL/OGR2OGRWIN

gdal.msi

Page 64: D3 workshop

TOPOJSONnpm install –g topojson

Page 65: D3 workshop

HTTP SERVERnpm install –g http-server

Page 66: D3 workshop

CONVERTING TO GEOJSONogr2ogr \ -f GeoJSON \ -where "iso_a2 = 'BY'" \ states.geojson \ ne_10m_admin_1_states_provinces.shp

ogr2ogr \ -f GeoJSON \ -where "iso_a2 = 'BY'" \ places.geojson \ ne_10m_populated_places.shp

ISO 3166-1 alpha-2

Page 67: D3 workshop

CONVERTING TO TOPOJSONtopojson \ --id-property iso_3166_2 \ -p name=NAME \ -p name \ -o belarus.topojson \ states.geojson \ places.geojson

ISO 3166-2

Page 68: D3 workshop

LOADING DATAd3.json('belarus.topojson', function (error, data) { console.log(data);}

Page 69: D3 workshop

SVG VS CANVASD3 support both of them.

Page 70: D3 workshop

DEMO MAP V.1

Page 71: D3 workshop

CONVERTING TOPOJSON BACK TO GEOJSONvar states = topojson.feature(data, data.objects.states);

Page 72: D3 workshop

PROJECTION DEMO

see details

Page 73: D3 workshop
Page 74: D3 workshop

PROJECTIONvar projection = d3.geo.mercator() .translate([400, 400]) .rotate([-27.55, 0]) .center([0, 53.916667]) .scale(2200);

Page 75: D3 workshop

GEO PATH GENERATORvar path = d3.geo.path() .projection(projection);

Page 76: D3 workshop

DEMO MAP V.2

Page 77: D3 workshop

DRAWING BOUNDARIESvar mesh = topojson.mesh( belarus, belarus.objects.states, function(a, b) { return a !== b; });

svg.append('path') .datum(mesh) .attr('d', path) .attr('class', 'state-boundary');

Page 78: D3 workshop

DRAWING PLACESPOINTS

var places = topojson.feature(data, data.objects.places);

//POINTSsvg.append('path') .datum(places) .attr('d', path) .attr('class', 'place-point');

Page 79: D3 workshop

DRAWING PLACESLABELS

//LABELSsvg.selectAll('.place-label') .data(places.features) .enter().append('text') .attr('class', function (d) { return 'place-label ' + d.properties.name; }) .attr('transform', function(d) { return 'translate(' + projection(d.geometry.coordinates) + ')'; }) .attr('dy', function (d) { if(d.properties.name === 'Maladzyechna') { return '-0.35em' } return '.35em'; }) .attr('dx', 7) .text(function(d) { return d.properties.name; });

Page 80: D3 workshop

DEMO MAP V.3

Page 81: D3 workshop

HELPFUL TOOLSMapShaperGeoJSON.IOQGIS

Page 82: D3 workshop

BYE BYE