introduction to d3js (and svg)

38
Zahid Mian Part of the Brown-bag Series

Upload: zahid-mian

Post on 18-Aug-2015

24 views

Category:

Data & Analytics


2 download

TRANSCRIPT

Page 1: Introduction to d3js (and SVG)

Zahid MianPart of the Brown-bag Series

Page 2: Introduction to d3js (and SVG)

SVG Basic Shapes Paths Javascript vs. D3js Creating a Bar Graph Scaling What Next?

Page 3: Introduction to d3js (and SVG)

SVG (Scalable Vector Graphics)

Scalable images

Open standard

Files saved as standard XML

Need to have good command of Javascript D3js is a library written in javascript

<script src="http://d3js.org/d3.v3.min.js" charset="utf-8">

D3js makes it easy to manipulate SVG graphics

Page 4: Introduction to d3js (and SVG)

D3 = Data Driven Documents Produce interactive visualizations (web) Has several libraries to help with creating

graphics Focus on the visualization part (not the code) Support for binding data

Page 5: Introduction to d3js (and SVG)

Selections CSS-style selector to select DOM nodes

Manipulations (append, remove, etc.) Transitions

“smoothly” interpolate attributes of graphic, creating an aesthetically pleasing visual

Better than recreating each element Data-binding

Use a dataset (json, csv, javascript arrays, etc.) to allow D3 to create an object for each element

Page 6: Introduction to d3js (and SVG)

Based on a coordinate system with (0,0) at top left

Basic shapes include

Lines, Rectangles, Circles, and Polygons

Paths allow highly customized polygons Using basic shapes to create interactive

charts like bar charts, area charts, pie charts More Advanced creations are possible

Page 7: Introduction to d3js (and SVG)

<body><svg width=400 height=520 >

<line x1=10 y1=50 x2= 300 y2= 200 stroke-width="10" stroke="red" stroke-linecap="round"/>

<rect width=100 height=50 x=150 y=25 rx=40 ry=10 stroke-width=2 stroke=steelblue fill=#888 fill-opacity=.5 />

<circle cx=62 cy=150 r=25 stroke-width=5 stroke=steelbluefill=#888 />

<polygon points="60,250 10,420 115, 420" />

<path d="M 120 120, L 220 220, 420 120 Z" stroke="steelblue" stroke-width="2" fill="lightyellow"></path>

</body>

Page 8: Introduction to d3js (and SVG)

d3.select("body") // select <body> tag.append("svg") // add <svg> tag

.attr("width", "100") // width of svg, use default for height.append("rect") // add <rect> element

.attr("width", 50) // set attribute of rect

.attr("height", 150) // set attribute of rect

.attr("x", 25) // move 25 px from left of svg

.attr("y", 25) // move 25 px from top of svg

.style("fill", "blue"); // add some style

Page 9: Introduction to d3js (and SVG)

d3.select("body") // select <body> tag.append("svg") // add <svg> tag

.attr("width", "100").append("circle") // add <circle> element

.attr("cx", 50) // move center of circle 50 px from left of svg

.attr("cy", 50) // move center of circle 50 px from top of svg

.attr("r", 25) // radius of circle.style("fill", "blue"); // add some style

Page 10: Introduction to d3js (and SVG)

//The data for our line; simply an array of x,y coordinates for each line segmentvar lineData = [ { "x": 1, "y": 5}, { "x": 20, "y": 20},

{ "x": 40, "y": 10}, { "x": 60, "y": 40},{ "x": 80, "y": 5}, { "x": 100, "y": 60}];

//This accessor function will use the x,y coordinates and create a path of points var lineFunction = d3.svg.line() // we’ll revisit this later

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

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

.interpolate("linear"); // we’ll revisit this later

//The SVG Containervar svgContainer = d3.select("body").append("svg")

.attr("width", 200)

.attr("height", 200);

//The line SVG Path we drawvar lineGraph = svgContainer.append("path")

.attr("d", lineFunction(lineData)) // concept of dynamic property; calls the lineFunctiondefined above

.attr("stroke", "blue")

.attr("stroke-width", 2)

.attr("fill", "none");

Interpolate(“linear”)

Interpolate(“step-before”)

Page 11: Introduction to d3js (and SVG)

d3.select("body").append("svg").attr("width", 100).attr("height", 100).append("text").text("hello world") .attr("stroke", "blue").attr("stroke-width", 1).attr("x", 10).attr("y", 10).attr("transform","rotate(25)");

d3.select("body").append("svg").append("text").text("hello world") .attr(

{stroke: "blue","stroke-width": "0.5",x: 10,y: 10,transform: "rotate(25)"});

Javascript shorthand for creating a bag of properties

Page 12: Introduction to d3js (and SVG)

d3.select("body").append("svg")

.attr("width", 350)

.attr("height", 220)// add <polygon> element.append("polygon")

.attr("points", "200,10 250,190 160,210")

.attr("fill", "green")

.attr("stroke", "red")

.attr("stroke-width", 3);

Page 13: Introduction to d3js (and SVG)

d3.select("body").append("svg")

.attr("width", 500)

.attr("height", 300).append("path")

.attr("d", "M 100 350 Q 150 -300 300 0")

.attr("fill", "green") // add some style.attr("stroke", "red").attr("stroke-width", 3);

M = moveto

L = lineto

H = horizontal lineto

V = vertical lineto

C = curveto

S = smooth curveto

Q = quadratic Bézier curve

T = smooth quadratic Bézier curveto

A = elliptical Arc

Z = closepath

Page 14: Introduction to d3js (and SVG)

D3.js includes a set of Path Data Generators helper classes for generating SVG Path instructions. d3.svg.line - create a new line generator d3.svg.line.radial - create a new radial line generator d3.svg.area - create a new area generator d3.svg.area.radial - create a new radial area generator d3.svg.arc - create a new arc generator d3.svg.symbol - create a new symbol generator d3.svg.chord - create a new chord generator d3.svg.diagonal - create a new diagonal generator d3.svg.diagonal.radial - create a new radial diagonal

generator

Page 15: Introduction to d3js (and SVG)

var arc = d3.svg.arc() // What does this do?.innerRadius(20).outerRadius(100).startAngle(0).endAngle(Math.PI) ;

// Angles are specified in radians; 0 corresponds to 12 o’clock (negative y) and proceeds clockwise, repeating at 2π

var chart = d3.select("body").append("svg:svg")

.attr("width", 200)

.attr("height", 250).append("svg:g")

.attr("transform", "translate(50,150)") ;

chart.append("svg:path").attr("fill", "green").attr("d", arc) ;

endAngle(Math.PI)

endAngle(0.5* Math.PI)

Page 16: Introduction to d3js (and SVG)

Where are we?

We know about SVG shapes

We know a little bit about D3js

We can create different shapes using D3js syntax

What haven’t we done?

No Data examples

No interactive examples (can’t show much in ppt)

Page 17: Introduction to d3js (and SVG)

var data = [{x: 5, y: 15, w: 10, h:25},{x: 20, y: 5, w: 10, h:35},{x: 35, y: 20, w: 10, h:20}

];var svg = d3.select("body").append("svg") .attr("width", 100) .attr("height", 60);

var grp = svg.append("g").selectAll("rect") .data(data) .enter() .append("rect") .attr({x: function(d){ return d.x;},y: function(d){ return d.y;},width: function(d){return d.w;},height: function(d) {return d.h;},fill: "#95B3D7"

});

var data = [{x: 5, y: 15, w: 10, h:25},{x: 20, y: 5, w: 10, h:35},{x: 35, y: 20, w: 10, h:20}

];var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");svg.setAttribute("width", 100);svg.setAttribute("height", 60);var svgNS = svg.namespaceURI;for(var z =0; z<data.length; z++){var rect = document.createElementNS(svgNS,'rect');

rect.setAttribute('x',data[z].x);rect.setAttribute('y',data[z].y);rect.setAttribute('width',data[z].w);rect.setAttribute('height',data[z].h);rect.setAttribute('fill','#95B3D7');svg.appendChild(rect);

}document.body.appendChild(svg);

D3 Way (no looping) Javascript

Page 18: Introduction to d3js (and SVG)

Greater flexibility with more complex data Handles binding automatically Easier transitions grp.attr("transform", "translate(20,20)");

Moves the entire group 20x20

Page 19: Introduction to d3js (and SVG)

A little tough to understand at first Makes sense after reviewing examples General Pattern:

// Update… var p = d3.select("body").selectAll("p")

.data([4, 8, 15, 16, 23, 42]) // array of numbers

.text(String);// Enter… this will be called for each data elementp.enter().append("p")

.text(String);// Exit…p.exit().remove();

Page 20: Introduction to d3js (and SVG)

// Update… var p = d3.select("body").selectAll("p")

.data([4, 8, 15, 16, 23, 42]) // join “p” with data items

.text(function(d){console.log(d);return (d*d).toString();

});

Notice we can call a function to get the data element

Since there are no “p” tags in the body, nothing is displayed

No log information is created

<body>

</body>

html output

Page 21: Introduction to d3js (and SVG)

var p = d3.select("body").selectAll("p").data([4, 8, 15, 16, 23, 42]).text(function(d){console.log(d); return d.toString();});

p.enter().append("p").text(function(d) {console.log ("value of d is: " + d.toString()); return (d*2).toString();});

Notice the console output (original values) and the eventual data that’s rendered (value doubled)

Essentially, create a “p” tag for each data element

<body>

<p>8</p><p>16</p><p>30</p><p>32</p><p>46</p><p>84</p>

</body>

console.log output

html output

Page 22: Introduction to d3js (and SVG)

This time the html body tag has some <p> tags defined like this:<body><p>this is p1</p><p>this is p2</p><p>this is p3</p>

</body>

Here’s the D3 “update” code:var p = d3.select("body").selectAll("p").data([4, 8, 15, 16, 23, 42]).text(function(d){console.log("d in update:" + d.toString()); return d.toString();

});

Notice the original <p> text has been replaced

<body>

<p>4</p><p>8</p><p>15</p>

</body>

html output

console.log output

Page 23: Introduction to d3js (and SVG)

The html body tag has some <p> tags defined like this:<body><p>this is p1</p><p>this is p2</p><p>this is p3</p>

</body>

Here’s the D3 Enter code:p.enter().append("p").text(function(d) {console.log ("value of d is: " + d.toString()); return (d*2).toString();});

Notice the last three <p> tags have the doubled value

<body><p>4</p><p>8</p><p>15</p><p>32</p><p>46</p><p>84</p>

</body>

html output

console.log output

Page 24: Introduction to d3js (and SVG)

var data = [4, 8, 15, 16, 23, 42];

function createSomething(){var p = d3.select("body").selectAll("p").data(data).text(function(d){

console.log("d in update:" + d.toString()); return d.toString();});

p.enter().append("p").text(function(d) {console.log ("value of d is: " + d.toString()); return (d*2).toString();})// attach click event to remove an element.on("click", function(d, i){

console.log(“onclick d, i: “ + d + “, “ + i);data.splice(d, 1); // let’s remove a value

from datacreateSomething();

});

// Exit ... p.exit().remove();}

createSomething();Clicked on 46. What happened to 32 and 84?

From the “update”

From the Enter selection

The onclickremoved an item from the array

When data is updated (removed), one of the <p> is also removed. Notice that the values are not doubled. That’s because the update selection was executed, not Enter. The log output confirms that.

Page 25: Introduction to d3js (and SVG)

// what would happened if we added an element ???var data = [4, 8, 15, 16, 23, 42];

function createSomething(){var p = d3.select("body").selectAll("p").data(data).text(function(d){console.log("d in update:" + d.toString()); return d.toString();});

p.enter().append("p").text(function(d) {console.log ("value of d is: " + d.toString()); return (d*2).toString();}).on("click", function(){

console.log(“addding 10 to data“);// add the number 10 to the top of arrayd.splice(0,0, 10);createSomething();

});

// Exit ... p.exit().remove();}

createSomething();

Notice that the new value was joined with the first <p>; the first 6 <p> were updated, and the 7th was inserted (that’s why it has the double value)Clicked on 46. What happened

to 32?

Page 26: Introduction to d3js (and SVG)

// what would happened if we added an element ???var data = [4, 8, 15, 16, 23, 42];

function createSomething(){var p = d3.select("body").selectAll("p").data(data).text(function(d){console.log("d in update:" + d.toString()); return d.toString();});

p.enter().append("p").text(function(d) {console.log ("value of d is: " + d.toString()); return (d*2).toString();}).on("click", function(){

console.log(“addding 10 to data“);// add the number 10 to the bottom of arrayd.splice(4,0, 10);createSomething();

});

// Exit ... p.exit().remove();}

createSomething();

What will be displayed when you click on 46? Look at the log output.

Page 27: Introduction to d3js (and SVG)

Understanding the Update, Enter, Exit selections is critical

Now we know about SVG graphics AND D3 Scripting (a little bit) AND Selections So now you are only bound by your

imagination (and a bit of geometry)

Page 28: Introduction to d3js (and SVG)

A Bar chart is simply a set of rectangles Let’s use D3 to create some rectangles Here’s something that looks like a bar chart

with 5 rectangles

Page 29: Introduction to d3js (and SVG)

<!DOCTYPE html><html><head><meta charset="utf-8"><title>JS Bin</title><script

src="http://d3js.org/d3.v3.min.js"></script><script><!– on right side -->

</script></head><body>

</body></html>

var w = 300;var h = 100;var padding = 2;var data = [15, 10, 50, 20, 25];

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

svg.selectAll("rect") // select all rect.data(data) // our data .enter() // cross your fingers.append("rect") // it will append rect.attr("x", function(d,i) {return i*(w/dataset.length);

}) // set x … d is data and i is index of data.attr("y", function(d, i){return h-(d);

}) // set y … remember y start in top-left corner.attr("width", w/dataset.length - padding).attr("height", function(d) {return d;

});

Page 30: Introduction to d3js (and SVG)

var w = 300;var h = 200;var padding = 2;var dataset = [15, 10, 45, 20, 25];

var svg = d3.select("body").append("svg").attr("width", w)

.attr("height", h);

function getColor(v) {if (v<=20) {return "#666666"; }else if(v<40) {return "#FF5010";}else {return "#FF0000";}

}

svg.selectAll("rect") // select all rect.data(dataset) // our data .enter() // will append if doesn't exist.append("rect") // it will append rect

.attr("x", function(d,i) {return i*(w/dataset.length);

}).attr("y", function(d, i){

return h-(d*4);}).attr("width", w/dataset.length - padding).attr("height", function(d) {

return d*4;}).attr("fill", function(d) {return getColor(d);});

svg.selectAll("text").data(dataset).enter().append("text").text(function(d) {return d;}).attr({

"text-anchor": "middle",x: function(d,i){

return i*(w/dataset.length)+(w/dataset.length - padding) /2;},y: function(d) {return h-(d*4)+14;}, // drop it inside the bar"font-family": "sans-serif","font-size": 12,"fill": "#ffffff"

});

Page 31: Introduction to d3js (and SVG)

var w = 300, //widthh = 300, //heightr = 100, //radiuscolor = d3.scale.category20c(); //builtin range of colors

data = [{"label": "one","value": 20

}, {"label": "two","value": 50

}, {"label": "three","value": 30

}];

var vis = d3.select("body").append("svg:svg") //create the SVG element inside the <body>

.data([data]) //associate our data with the document

.attr("width", w) //set the width and height of our visualization (these will be attributes of the <svg> tag

.attr("height", h).append("svg:g") //make a group to hold our pie chart

.attr("transform", "translate(" + r + "," + r + ")"); //move the center of the pie chart from 0, 0 to radius, radius

var arc = d3.svg.arc() //this will create <path> elements for us using arc data.outerRadius(r);

var pie = d3.layout.pie() //this will create arc data for us given a list of values.value(function(d) {

return d.value;}); //we must tell it out to access the value of each element in our data array

var arcs = vis.selectAll("g.slice") //this selects all <g> elements with class slice (there aren't any yet).data(pie) //associate the generated pie data (an array of arcs, each having startAngle, endAngle and

value properties) .enter() //this will create <g> elements for every "extra" data element that should be associated with a

selection. The result is creating a <g> for every object in the data array.append("svg:g") //create a group to hold each slice (we will have a <path> and a <text> element

associated with each slice).attr("class", "slice"); //allow us to style things in the slices (like text)

arcs.append("svg:path").attr("fill", function(d, i) {

return color(i);}) //set the color for each slice to be chosen from the color function defined above

.attr("d", arc); //this creates the actual SVG path using the associated data (pie) with the arc drawing function

arcs.append("svg:text") //add a label to each slice.attr("transform", function(d) { //set the label's origin to the center of the arc

//we have to make sure to set these before calling arc.centroidd.innerRadius = 0;d.outerRadius = r;return "translate(" + arc.centroid(d) + ")"; //this gives us a pair of coordinates like [50, 50]

}).attr("text-anchor", "middle") //center the text on it's origin

.text(function(d, i) {return data[i].label;

}); //get the label from our original data array

Page 32: Introduction to d3js (and SVG)

Scaling is important for creating Axis Can also be used to resize graphics Use d3.scale.linear() to create scale

var scale = d3.scale.linear().domain([130,350]) // min/max.range([10,100]); // output range;

// now use the scale object to get scaled valueconsole.log(scale(130)); // 10console.log(scale(350)); // 100console.log(scale(300)); // 79.54console.log(scale(150)); // 18.18

Page 33: Introduction to d3js (and SVG)

Transitions deal with animation; Not possible to show in a presentation (see demos later)

A little ironic that we can’t show transitions in ppt

Very Powerful feature of D3 A very simply transition:

d3.select("body") .style("color", "green") // make the body green.transition() .style("color", "red"); // then transition to red

https://www.youtube.com/watch?v=vLk7mlAtEXI http://bl.ocks.org/mbostock/3943967

Page 34: Introduction to d3js (and SVG)

http://bl.ocks.org/mbostock/32bd93b1cc0fbccc9bf9

Page 35: Introduction to d3js (and SVG)
Page 36: Introduction to d3js (and SVG)

https://github.com/mbostock/d3/wiki/Gallery Source code available for all examples Copy source and play with it in a javascript

environment (jsfiddle.net, jsbin.com, etc.) Use debugger and console.log liberally to

better understand what’s happening

Page 37: Introduction to d3js (and SVG)

Debugging in javascript Examples from today Examples from NYTimes.com Examples from around the Internet

Page 38: Introduction to d3js (and SVG)