D3 workshop

Post on 27-Aug-2014

249 views 4 download

description

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

Transcript of D3 workshop

D3 WORKSHOP

DATADRIVEN

DOCUMENTS

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

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

CREATE YOUR OWN VISUALIZATIONS

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

highchartsjqPlotnvd3...

SOURCE OF INSPIRATION

bl.ock.org

COLLISION DETECTION

see details

CHORD DIAGRAM

0k

5k

10k

15k

20k

25k

0k

5k

10k

15k20k

0k

5k

10k

15k

20k

25k

30k

35k

40k0k

5k

see details

FLEXIBLE TRANSITIONSAAPL

AMZN

IBM

MSFT

see details

COOL... BUTI STILL WANNA BAR CHART!

DATA

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

USAGE

barChart(data);

SIMPLE BAR CHART

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>

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

MIN D3

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

MAX D3

CREATE 3 DIVS

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

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

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

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

ENTER

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

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

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

EXIT

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

...

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

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

MORE ABOUT SELECTIONS AND JOINSThree Little CirclesThinking with JoinsHow Selections Work

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

range.

learn more

SCALES

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

scale(50); // return 60

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

TRANSITIONSINTERPOLATE VALUES OVER TIME

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

learn more

SVG <CIRCLE>

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

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

TRANSITION DEMO

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

BREAK

DONUT CHART

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>

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>

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

see more

AND SOME MORE...

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}]*/

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"

DEMO DONUT CHART V.1

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

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

DEMO DONUT CHART V.2

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

DEMO DONUT CHART V.3

ARC TWEEN

see details

DEMO DONUT CHART V.4

BREAK

Original:

LET'S DRAW BELARUS

Let’s Make a Map

FINDING DATA SOURCESGovernment ;)GeoCommonsNaturalEarthData

ESRI SHAPEFILEPopular geospatial vector data format for geographic

information system software.

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

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

TOPOJSONExtension of GeoJSON that encodes topology.

Join shared lines into arcs.

BENEFITS:

smaller size (80% smaller)automatic mesh generation

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]

INSTALLING TOOLSGDAL/OGR2OGR

TOPOJSON

HTTP SERVER

GDAL/OGR2OGRUBUNTU

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

GDAL/OGR2OGRMAC

brew install gdal

GDAL/OGR2OGRWIN

gdal.msi

TOPOJSONnpm install –g topojson

HTTP SERVERnpm install –g http-server

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

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

ISO 3166-2

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

SVG VS CANVASD3 support both of them.

DEMO MAP V.1

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

PROJECTION DEMO

see details

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

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

DEMO MAP V.2

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

DRAWING PLACESPOINTS

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

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

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

DEMO MAP V.3

HELPFUL TOOLSMapShaperGeoJSON.IOQGIS

BYE BYE