O slideshow foi denunciado.
Seu SlideShare está sendo baixado. ×

Introduction to d3js (and SVG)

Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Anúncio
Próximos SlideShares
D3js learning tips
D3js learning tips
Carregando em…3
×

Confira estes a seguir

1 de 38 Anúncio
Anúncio

Mais Conteúdo rRelacionado

Diapositivos para si (20)

Quem viu também gostou (20)

Anúncio

Semelhante a Introduction to d3js (and SVG) (20)

Anúncio

Mais recentes (20)

Introduction to d3js (and SVG)

  1. 1. Zahid Mian Part of the Brown-bag Series
  2. 2.  SVG  Basic Shapes  Paths  Javascript vs. D3js  Creating a Bar Graph  Scaling  What Next?
  3. 3.  SVG (ScalableVector 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
  4. 4.  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
  5. 5.  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
  6. 6.  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
  7. 7. <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=steelblue fill=#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>
  8. 8. 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
  9. 9. 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
  10. 10. //The data for our line; simply an array of x,y coordinates for each line segment var 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 Container var svgContainer = d3.select("body").append("svg") .attr("width", 200) .attr("height", 200); //The line SVG Path we draw var lineGraph = svgContainer.append("path") .attr("d", lineFunction(lineData)) // concept of dynamic property; calls the lineFunction defined above .attr("stroke", "blue") .attr("stroke-width", 2) .attr("fill", "none"); Interpolate(“linear”) Interpolate(“step-before”)
  11. 11. 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
  12. 12. 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);
  13. 13. 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 = ellipticalArc Z = closepath
  14. 14.  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
  15. 15. 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)
  16. 16.  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)
  17. 17. 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); D3Way (no looping) Javascript
  18. 18.  Greater flexibility with more complex data  Handles binding automatically  Easier transitions  grp.attr("transform", "translate(20,20)");  Moves the entire group 20x20
  19. 19.  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 element p.enter().append("p") .text(String); // Exit… p.exit().remove();
  20. 20. // 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
  21. 21. 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
  22. 22. 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
  23. 23. 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
  24. 24. 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 data createSomething(); }); // Exit ... p.exit().remove(); } createSomething(); Clicked on 46.What happened to 32 and 84? From the “update” From the Enter selection The onclick removed 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.
  25. 25. // 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 array d.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?
  26. 26. // 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 array d.splice(4,0, 10); createSomething(); }); // Exit ... p.exit().remove(); } createSomething(); What will be displayed when you click on 46? Look at the log output.
  27. 27.  Understanding the Update, Enter, Exit selections is critical  Now we know about SVG graphicsAND  D3 Scripting (a little bit) AND  Selections  So now you are only bound by your imagination (and a bit of geometry)
  28. 28.  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
  29. 29. <!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; });
  30. 30. 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" });
  31. 31. var w = 300, //width h = 300, //height r = 100, //radius color = 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.centroid d.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
  32. 32.  Scaling is important for creatingAxis  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 value console.log(scale(130)); // 10 console.log(scale(350)); // 100 console.log(scale(300)); // 79.54 console.log(scale(150)); // 18.18
  33. 33.  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
  34. 34. http://bl.ocks.org/mbostock/32bd93b1cc0fbccc9bf9
  35. 35.  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
  36. 36.  Debugging in javascript  Examples from today  Examples from NYTimes.com  Examples from around the Internet

×