Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

A Quick and Dirty D3.js Tutorial

1,130 views

Published on

This material is for a 3-hour course of D3.js

Published in: Technology
  • Be the first to comment

A Quick and Dirty D3.js Tutorial

  1. 1. A Quick & Dirty D3.js Young-Ho Kim Human-Computer Interaction Lab Dept. of Computer Science & Engineering Seoul National University Course
  2. 2. Course | Young-Ho Kim – A Quick and Dirty D3.js Overview In this course, we will go through… 1. A quick & dirty introduction of D3.js 2. Play with D3 on HTML document The material is based on my experience of learning by many people’s blogs, slides, tutorials, and books. It may have grammatical issues and technical issues about D3. If you find anything strange, please let me know. yhkim@hcil.snu.ac.kr About This Course 2
  3. 3. Course | Young-Ho Kim – A Quick and Dirty D3.js Overview 1. Brief History of D3 2. Data Preparation 3. Basic Drawing 4. Advanced Chart Drawing 5. Interaction 6. Transitions 7. Other Features 8. Tips 9. Q&A Table of Contents 3
  4. 4. Course | Young-Ho Kim – A Quick and Dirty D3.js Overview D3.js is a JavaScript library for manipulating documents based on data – d3js.org What is D3.js? 4 Data-Driven Documents
  5. 5. Course | Young-Ho Kim – A Quick and Dirty D3.js Overview • D3 is a research project in Stanford Vis Group. • D3 was written and maintained by Micheal Bostock. • Proposed at InfoVis 2011. Micheal Bostock, Vadim Ogievetsky, and Jeffrey Heer. D3: Data-Driven Documents. • descendant of ProtoVis (2009) chart drawing library. 5 What is D3.js?
  6. 6. Course | Young-Ho Kim – A Quick and Dirty D3.js Why D3.js? People are getting more familiar with charts and visualization. Data Journalism, Big Data, Infographics… 6 Today’s Visualization is Dynamic Daily MaverickInteractive visualizations of NY Times
  7. 7. Course | Young-Ho Kim – A Quick and Dirty D3.js Why D3.js? Digital media enables high interactivity Information visualization is no more a static chart printed on paper. 7 Today’s Visualization is Dynamic Radik Sadana et al. TouchVis Tipco Spotfire
  8. 8. Course | Young-Ho Kim – A Quick and Dirty D3.js Why D3.js? Web is the most accessible, and actively-used platform for interactive visualization. Don’t need to install stand-alone applications, One-sided modification(bug fix, upgrade, …) is available. 8 Today’s Visualization is Dynamic
  9. 9. Course | Young-Ho Kim – A Quick and Dirty D3.js What is D3.js? • D3 helps you draw visual elements based on the arrays of the data. • You can dynamically modify DOM element of an HTML do cument without explicitly looping among the data points. 9 Simple description on D3
  10. 10. Course | Young-Ho Kim – A Quick and Dirty D3.js Tutorial Using D3 demands basic knowledges of... • JavaScript : D3 is a JavaScript library. • HTML : D3 substitutes DOM elements for drawing. • CSS : D3 visualizations can be stylized using CSS. • jQuery : D3 resembles jQuery much. But a little different in terms of its syntax. You will have to use jQuery together for more complicate d interactive visualization. 10 Prerequisites
  11. 11. Course | Young-Ho Kim – A Quick and Dirty D3.js Tutorial Lets use D3.js! Tutorial 1. Prepare to use D3 11
  12. 12. Course | Young-Ho Kim – A Quick and Dirty D3.js Tutorial • A Web browser and a text editor • We will use FireFox or Safari in this tutorial for some reasons. • You may use any text editor familiar with you. • Developer tools on a browser are very helpful for JavaScript programing. 12 Tutorial 1. Prepare to use D3 (Cont.)
  13. 13. Course | Young-Ho Kim – A Quick and Dirty D3.js Tutorial http://hcil.snu.ac.kr/~muclipse/d3_course_tutorial_yhkim.zip Download the tutorial files. Start tutorial from starthere.html file. The tutorial is incremental and sequential. If you didn’t catch the tutorial, skip it by using the answer files and use it as a start point from the next tutorial. 13 Tutorial 1. Prepare to use D3 (Cont.)
  14. 14. Data Preparation
  15. 15. Course | Young-Ho Kim – A Quick and Dirty D3.js Data Preparation • Building data table to be used in your visualization is almost a half of the visualization process. • A scheme of the data is crucial for the conciseness of your c ode and the difficulty of your entire development. • Deriving a table from a chart is much more difficult than dra wing a chart from a table. 15 Using Data Table on Interactive Visualization
  16. 16. Course | Young-Ho Kim – A Quick and Dirty D3.js Data Preparation Imagine you want to draw a bar chart like this. 16 Using Data Table on Interactive Visualization Sally Tom John 5 10 7.5
  17. 17. Course | Young-Ho Kim – A Quick and Dirty D3.js Data Preparation It’s not hard to derive this table from the chart. 17 Using Data Table on Interactive Visualization Sally Tom John 5 10 7.5 Sally 5 Tom 10 John 7.5
  18. 18. Course | Young-Ho Kim – A Quick and Dirty D3.js Data Preparation D3 is a JavaScript so the table must be the form of JSON… 18 Using Data Table on Interactive Visualization Sally 5 Tom 10 John 7.5 { “Sally”:5, “Tom”:10, “John”:7.5 } [{“Sally”:5}, {“Tom”:10}, {“John”:7.5}] or
  19. 19. Course | Young-Ho Kim – A Quick and Dirty D3.js Data Preparation You will have a very hard time with these data structures. 19 Using Data Table on Interactive Visualization Sally 5 Tom 10 John 7.5 { “Sally”:5, “Tom”:10, “John”:7.5 } [{“Sally”:5}, {“Tom”:10}, {“John”:7.5}] or
  20. 20. Course | Young-Ho Kim – A Quick and Dirty D3.js Data Preparation Every data table needs ‘schema’ – column names. In other words, make your data structure to be “loopable”. 20 Using Data Table on Interactive Visualization Name Value Sally 5 Tom 10 John 7.5 [{“Name”:“Sally”, “Value”:5}, {“Name”:“Tom”, “Value”:10}, {“Name”:“John”, “Value”:7.5}] A key must be a schema(column), not a value.
  21. 21. Course | Young-Ho Kim – A Quick and Dirty D3.js Data Preparation • D3 provide functions to load data from an URL. d3.csv(URL, callback) d3.json(URL, callback) • Tsv, text, xml, html are also supported. • I recommend using JSON because it is versatile. • Data is loaded asynchronously. So we should wait until t he loading is finished : Do everything in a callback. 21 Loading Data in D3 d3.json(URL, function(error, json){ if(json!=null){ //Do Something } });
  22. 22. Course | Young-Ho Kim – A Quick and Dirty D3.js Data Preparation Add this code inside your <script> block. 22 Tutorial 2. Loading Data Table d3.json(“data.json”, function(error, json){ if(json!=null){ console.log(json); } });
  23. 23. Course | Young-Ho Kim – A Quick and Dirty D3.js Data Preparation Add this code inside your <script> block. 23 Tutorial 2. Loading Data Table (Cont.) d3.json(“data.json”, function(error, json){ if(json!=null){ console.log(json); } }); This callback is invoked when the loading finishes. The second parameter contains loaded JSON object if loaded without an error.
  24. 24. Basic Drawing
  25. 25. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing D3 is similar to jQuery. Selectors, Styles, Attributes, Text… but its syntax is slightly different. D3 visualizes by substituting DOM elements. Appending new elements, removing elements, modifying styles and a ttributes of elements… 25 Drawing Mechanism of D3 codefactor.com
  26. 26. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing Both jQuery and D3 starts with selection 26 D3 vs jQuery Basics d3.select(“body”) $(“body”) Appending new DOM element d3.select(“body”).append(“p”) $(“body”).append(“<p></p>”) D3 function is cascaded to descendant. d3.select(“body”).append(“p”).text(“test”) Returns <p> child element selection.
  27. 27. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing • Let’s draw an HTML table dynamically. • Write this code somewhere in your <script> block. 27 Tutorial 3. Drawing Table Dynamically var table = d3.select(“body”).append(“table”); var row1 = table.append(“tr”); row1.append(“td”).text(“Sally”); row1.append(“td”).text(“5”); var row2 = table.append(“tr”); row2.append(“td”).text(“Tom”); row2.append(“td”).text(“10”);
  28. 28. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing 28 Tutorial 3. Drawing Table Dynamically var table = d3.select(“body”).append(“table”); var row1 = table.append(“tr”); row1.append(“td”).text(“Sally”); row1.append(“td”).text(“5”); var row2 = table.append(“tr”); row2.append(“td”).text(“Tom”); row2.append(“td”).text(“10”); Save selection to variable if more than one child will be appended.
  29. 29. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing To draw elements in a data-driven way, you should understa nd a concept of Selections, Binding and Joins in D3. Data-driven Drawing 1. Select elements to be connected to data (Selection) 2. Bind data to the selection (Binding) 3. Add, Modify, or Remove elements based on data (Join) 29 Going Data-Driven Way
  30. 30. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing Elements are first ‘selected’ even if they don’t exist yet. • d3.selectAll(selector) : returns all elements with selector • d3.select(selector) : returns the first element with selector • D3 uses CSS3 selectors. • If no one matches the selector, they return an empty selection. 30 Selecting Elements
  31. 31. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing Now the data is connected to the selection. selection.data(array, key=null) This function pairs selected elements with an array of data values. → What if the number of data values are different from the s elected elements? → That’s what Join does. 31 Binding Data
  32. 32. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing Join handles 3 cases of the overlaps of Data and Nodes(selection). Enter: A set of newly added data. Not matched with current selection. Update: A set of already matched pairs of a data point and an element. Exit: A set of selected nodes the data of which do not exist anymore. 32 Joins Forget about Update and Exit for now.
  33. 33. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing D3 join functions returns selections with corresponding joi n set. • selection.data().enter() : returns the empty selection of el ements that should be newly added. • selection.data() : default data function returns an update se lection. • selection.data().exit() : returns selection of the elements that should be removed. 33 Joins (Cont.)
  34. 34. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing Let’s draw a bar chart in a data-driven way. Add this code inside your callback. 34 Tutorial 4. Div Bar Chart d3.json(“URL”, function(error, json){ if(json!=null){ //Write code here } });
  35. 35. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing 35 Tutorial 4. Div Bar Chart (Cont.) d3.json(“URL”, function(error, json){ if(json!=null){ d3.select(“body”) .selectAll(“div”) .data(json) .enter() .append(“div”); } }
  36. 36. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing 36 Tutorial 4. Div Bar Chart (Cont.) d3.json(“URL”, function(error, json){ if(json!=null){ d3.select(“body”) .selectAll(“div”) .data(json) .enter() .append(“div”); } } ←Use <div> for a bar. ←Bind data. ←Get enter selection ← Functions are applied to each selected element without using loops.
  37. 37. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing • You will see nothing because <div> is transparent in defa ult. • D3 provides functions to modify attributes and styles of DOM elements. • Attributes provide additional information about HTML elements i nside the tag. <div class=“contents”> • Styles provide style information about selections in CSS, or abo ut an element in “style” attribute. 37 Styles and Attributes
  38. 38. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing selection.attr(“attribute”, “value”) selection.attr(“attribute”, function(datum, index){return value}) Changes attribute of each selected element. If value is functio n, you can dynamically assign attribute on each element. 38 Styles and Attributes (Cont.) selection.style(“style”, “value”) selection.style(“style”, function(datum, index){return value}) Changes style. The style is applied to “style” attribute of each selected element, not globally in CSS.
  39. 39. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing Append some style functions to the selection to make our chart visible. 39 Tutorial 5. Div Bar Chart Styling d3.select(“body”) .selectAll(“div”) .data(json) .enter() .append(“div”) .style(“width”, function(d){return d.value * 5 + “px”;}) .style(“background”, “red”) .text(function(d){return d.value});
  40. 40. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing • Using div has many limitations on chart drawing. • SVG is more suitable for visualization. • SVG(Scalable Vector Graphics) is a vector image defined by X ML-based markups inside webpage. http://www.w3schools.com/svg/ • SVG graphic element is considered the same as other DOM ele ments in the HTML document. • Every geometric attributes are designated on attributes in tag, s ome attributes are also available in style. 40 Introduction to SVG
  41. 41. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing • SVG shares many styling properties with CSS. • Some distinction that may confusing: 41 SVG Styles vs CSS Styles CSS Style SVG Style(Attribute) size font-size color font-color background fill border-style stroke border-width stroke-width
  42. 42. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing • SVG drawing is different from classic HTML document. • SVG elements are not cascaded in layout. • They are defined under Cartesian coordinates inside the canvas of SVG image. 42 Preparing SVG Drawing <html><body> <svg width=“150” height=“150”> <rect x=“10” y=“20” width=“60” height=“30” fill=red/> </svg> </body></html>
  43. 43. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing • <svg> tag with “width” and “height” attributes must be defined as the outmost markup. • Topleft corner is (0,0). 43 Preparing SVG Drawing (Cont.) <svg width=“150” height=“150”> </svg> (0,0) (150,150)
  44. 44. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing rect (x,y,width,height) circle (cx, cy, r) ellipse (cx, cy, rx, ry) line (x1, y1, x2, y2) path (d) polygon (points) 44 Basic SVG Elements (geometric attributes)
  45. 45. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing • <text> draws text on the svg image. Similar to simple HTML text but provides more powerful styling and can be drawn anywhere. • <g> (group) groups its child elements and the position of group acts as an origin of its children. Group is really important in complicated visualization. You can reduce the amount of code by clever use of groups. 45 Other important SVG Elements
  46. 46. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing • Change your HTML bar chart to SVG. 46 Tutorial 6. Migration to SVG d3.select(“body”) .append(“svg”) .attr({width:500, height:500}) .selectAll(“rect”) .data(json) .enter() .append(“rect”) .attr(“width”, function(d){return d.value * 5}) .attr(“height”, 500/json.length - 2) .attr(“y”, function(d,i){return i * 500/json.length});
  47. 47. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing • Change your HTML bar chart to SVG. 47 Tutorial 6. Migration to SVG (Cont.) d3.select(“body”) .append(“svg”) .attr({width:500, height:500}) .selectAll(“rect”) .data(json) .enter() .append(“rect”) .attr(“width”, function(d){return d.value * 5}) .attr(“height”, 500/json.length - 2) .attr(“y”, function(d,i){return i * 500/json.length}); ←You can assign multiple attributes or styles at once. ↑ Unlike HTML, SVG elements are not cascaded so you should explicitly assign y position.
  48. 48. Course | Young-Ho Kim – A Quick and Dirty D3.js Basic Drawing Your code should look like this. 48 Tutorial 6. Migration to SVG (Cont.)
  49. 49. Advanced Chart Drawing
  50. 50. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing Now we can draw bars based on data. But we still need more things to make a complete chart. 50 Still Not enough to be a Complete Chart… ←The bar with maximum value do not exceed the canvas. ↑ Ordinary charts contains axes.
  51. 51. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Scale is a function that maps data value to the extent of real image coordinate under specific formula: • Quantitative scales including linear, log, power,… • Ordinal scales provide discrete positions for ordinal values. • Time scales provide linear mappings for time points on timeline. • When you draw data elements on SVG plane, it is convenient to set their positions with scales rather than calculating them by yourself. 51 Scales
  52. 52. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • d3.scale provide most of scale functions. d3.scale.linear(), d3.scale.ordinal(), d3.scale.log() … • Properties are cascaded to the end of these functions. • Linear Scale Properties: • domain([start, end]) : define the extent of data values. • range([start, end]) : define the extent of output coordinates. • Ordinal Scale Properties: • domain([values]) : specify all the values. • rangeBands([start, end]) : define the extent of output coordinates. 52 Scales (Cont.)
  53. 53. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing Usage example: var x = d3.scale.linear().domain([2,5]).range([0,10]); Now you can calculate mapped coordinate by simply calling x(dataValue). Ordinal/nominal scales are similar: var x = d3.scale.ordinal().domain([“A”, “B”, “C”]) .rangeBands([0, 10]); Now you can calculate mapped coordinate by simply calling x(“A”), x(“B”), or x(“C”). 53 Scales (Cont.)
  54. 54. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Define scale function on the top of callback, and replace the width calculation code. 54 Tutorial 7. Employing scales d3.json(“URL”, function(error, json){ if(json!=null){ var x = d3.scale.linear().domain([0, 100]).range([0, 500]); d3.select(“body”) … .attr(“width”, function(d){return x(d.value)}) .attr(“height”, 500/json.length - 2) .attr(“y”, function(d,i){return i * 500/json.length});
  55. 55. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Define scale function on the top of callback, and replace the width calculation code. 55 Tutorial 7. Employing scales d3.json(“URL”, function(error, json){ if(json!=null){ var x = d3.scale.linear().domain([0, 100]).range([0, 500]); d3.select(“body”) … .attr(“width”, function(d){return x(d.value)}) .attr(“height”, 500/json.length - 2) .attr(“y”, function(d,i){return i * 500/json.length}); Horizontal range of the SVG plane
  56. 56. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • D3 provide axis as a function that draws axis based on scale. • Axis component is attached to chart area in 4 directions: 56 Adding Axis 0 20 40 60 80 100 120 140 0 20 40 60 80 100 120 140 0 20 40 60 80 100 120 140 0 20 40 60 80 100 120 140 Top Bottom Left RightRed dots are pivot position of the axis
  57. 57. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing d3.svg.axis() Returns a function to add axis component to a selection. • axis.scale(scale) : assigns a scale for the axis. • axis.orient(orientation) : assigns an orientation for the axis. ( “left”, “top”, “right”, “bottom”) 57 Axis Component API
  58. 58. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • To add axis component in SVG, we need to prepare space. 58 Grouping Chart Regions SVG Chart(coordinate space) Left A xis Bottom Axis
  59. 59. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing In convention, chart elements are drawn in a group. 59 Grouping Chart Regions var padding = {left:50, top:10, right:10, bottom:50}; var chart = d3.select(“body”) .append(“svg”).attr({width:500, height:500}) .append(“g”) .attr(“transform”, “translate(” + padding.left + “,” + padding.top + “)”); Paddings are used to allocate space for axes. “Transform” attribute is used to translate group.
  60. 60. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • We will add a left and a bottom axes. • First, add paddings on the top of callback.. 60 Tutorial 8. Employing Axis d3.json(“URL”, function(error, json){ if(json!=null){ var padding = {left:50, top:10, right:10, bottom:50}; var chartWidth = 500 – padding.left – padding.right; var chartHeight = 500 – padding.top – padding.bottom; • chartWidth and chartHeight will be used in scales.
  61. 61. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing Define x-axis function. 61 Tutorial 8. Employing Axis (Cont.) var x = d3.scale.linear().domain([0, 100]).range([0, chartWidth]); var xAxis = d3.svg.axis().orient(“bottom”).scale(x); //This time we will use scale in y values, too. var names = json.map(function(d){return d.name}); var y = d3.scale.ordinal().domain(names) .rangeBands([0, chartHeight]); var yAxis = d3.svg.axis().orient(“left”).scale(y);
  62. 62. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Define chart area. 62 Tutorial 8. Employing Axis (Cont.) var chart = d3.select(“body”) .append(“svg”).attr({width:500, height:500}) .append(“g”) .attr(“transform”, “translate(” + padding.left + “,” + padding.top + “)”);
  63. 63. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Draw axis. 63 Tutorial 8. Employing Axis (Cont.) chart.append(“g”).attr(“class”, “x axis”) .attr(“transform”, “translate(0,” + chartHeight + “)”) .call(xAxis); chart.append(“g”).attr(“class”, “y axis”) .call(yAxis);
  64. 64. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Draw bars. 64 Tutorial 8. Employing Axis (Cont.) chart.selectAll(“rect”) .data(json) .enter() .append(“rect”) .attr(“width”, function(d){return x(d.value)}) .attr(“height”, chartHeight/json.length - 2) .attr(“y”, function(d){return y(d.name)});
  65. 65. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Now you have axes. 65 Tutorial 8. Employing Axis (Cont.)
  66. 66. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Your axis would look ugly. Let’s do some CSS. 66 Styling Chart 0 20 40 60 80 <path class=“domain” … > <g class=“tick” … > A tick and a value text are grouped. <line … > <text … >
  67. 67. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • The lines of the axis are <line> and <path> tags. We can style these in CSS or just in code. 67 Axis Stylesheets .axis path, .axis line{ fill:none; stroke-width:1px; stroke:black; }
  68. 68. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • The tick labels are <text> tags. 68 Axis Stylesheets .axis text{ font-size:10px; font-weight:bold; }
  69. 69. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Add <style> block. 69 Tutorial 9. Styling Axis <head> <style> .axis path, .axis line{ fill:none; stroke-width:1px; stroke: black; } .axis text{ font-size:10px; font-weight:bold; } </style> …
  70. 70. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • We may want our chart to look more elaborated. • e.g. Redundant encoding • We will use <group> for mappings. 70 Toward More Complicated Data Elements 50 75 120 100 80
  71. 71. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing For now, we paired each data value to one SVG element. 71 Grouping Elements per Data Point A 50 B 75 C 120 D 100 E 80 SVG Rect chart.selectAll(“rect”) .data(json) .enter() .append(“rect”)
  72. 72. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Now a data value is paired to a set of a rect and a text. 72 Grouping Elements per Data Point A 50 B 75 C 120 D 100 E 80 50 75 120 100 80 SVG Rect SVG Text
  73. 73. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • We will add values to our bars. • Modify our bar drawing code. 73 Tutorial 10. Redundant Encoding var bars = chart.selectAll(“g.bar”) .data(json) .enter() .append(“g”) .attr(“class”, “bar”) .attr(“transform”, function(d){return “translate(0,” + y(d.name) + “)”); • Topmost data mapping is replaced by “g”. • We defined y-position of bars on groups in advance.
  74. 74. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Each group has one rect and one text. 74 Tutorial 10. Redundant Encoding var barHeight = chartHeight/json.length – 2; bars.append(“rect”) .attr(“width”, function(d){return x(d.value)}) .attr(“height”, barHeight); bars.append(“text”) .attr(“fill”, “white”) .attr(“x”, function(d){return x(d.value) – 5}) .attr(“y”, barHeight/2) .attr(“dominant-baseline”, “middle”) .attr(“text-anchor”, “end”) .text(function(d){return d.value}); 86
  75. 75. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing • Each group has one rect and one text. 75 Tutorial 10. Redundant Encoding var barHeight = chartHeight/json.length – 2; bars.append(“rect”) .attr(“width”, function(d){return x(d.value)}) .attr(“height”, barHeight); bars.append(“text”) .attr(“fill”, “white”) .attr(“x”, function(d){return x(d.value) – 5}) .attr(“y”, barHeight/2) .attr(“dominant-baseline”, “middle”) .attr(“text-anchor”, “end”) .text(function(d){return d.value}); Right alignment, center in vertical position ←set content of the block. 86
  76. 76. Course | Young-Ho Kim – A Quick and Dirty D3.js Advanced Chart Drawing Now the values are encoded to the length and the text. 76 Tutorial 10. Redundant Encoding
  77. 77. Interaction
  78. 78. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions • D3 handles JavaScript event model to make the elements responsive. • D3 event works by adding event listeners to d3 selection. 78 Leveraging Advantages of Web
  79. 79. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions • type: type of event to response (e.g. “mouseover”, “mouseleave”, “click”, “mousedown”, “mouseup”) • function(d,i): event handler. d: a single corresponding data point (datum) i: the index of the data point • on() function returns selection itself, enabling cascading. 79 D3 Event API selection.on(type, function(d,i){})
  80. 80. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions • The parameters of handler function gives information about data. It is useful for printing interacted data. • ‘this’ in the scope of handler function indicates the DOM element itself. So you can get a selection of responded element by d3.select(this) 80 Event Handling selection.on(type, function(d,i){ //d, i : data-level handling //d3.select(this) : visualization-level handling });
  81. 81. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions • Let’s make our bar chart more interactive. We will highlight the bar which the mouse is hovering on. 81 Tutorial 11. Details-On-Demand
  82. 82. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions Append event functions to rect selections. 82 Tutorial 11. Details-On-Demand (Cont.) bars.append(“rect”) .attr(“width”, function(d){return x(d.value)}) .attr(“height”, barHeight) .on(“mouseover”, function(d,i){ d3.select(this).attr(“fill”, “orange”); }) .on(“mouseleave”, function(d,i){ d3.select(this).attr(“fill”, null); });
  83. 83. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions Append event functions to <rect> selections. 83 Tutorial 11. Details-On-Demand (Cont.) bars.append(“rect”) .attr(“width”, function(d){return x(d.value)}) .attr(“height”, barHeight) .on(“mouseover”, function(d,i){ d3.select(this).attr(“fill”, “orange”); }) .on(“mouseleave”, function(d,i){ d3.select(this).attr(“fill”, null); }); We didn’t use data information here. ←Change color when mouse entered ←Reset color when mouse leaved
  84. 84. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions • Now your rects are reactive to your mouse cursor. • Let’s do some more. What about showing the value labels only when mouse is hover? • The bar unit is a group of a <rect> and a <text>. To control both children, it is natural to attach event listener to each group, not the rect. 84 Tutorial 12. Details-On-Demand Advanced
  85. 85. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions • Change the text labels transparent. We will show the label only while the mouse is hovering on corresponding bar. 85 Tutorial 12. Details-On-Demand Advanced (Cont.) bars.append(“text”) .attr(“fill”, “white”) .attr(“x”, function(d){return x(d) – 5}) .attr(“y”, barHeight/2) .attr(“dominant-baseline”, “middle”) .attr(“text-anchor”, “end”) .attr(“display”, “none”) .text(function(d){return d.value});
  86. 86. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions • Remove event listener code from rect selections. 86 Tutorial 12. Details-On-Demand Advanced (Cont.) bars.append(“rect”) .attr(“width”, function(d){return x(d.value)}) .attr(“height”, barHeight); .on(“mouseover”, function(d,i){ d3.select(this).attr(“fill”, “orange”); }) .on(“mouseleave”, function(d,i){ d3.select(this).attr(“fill”, null); });
  87. 87. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions • Substitute the group selection code. 87 Tutorial 12. Details-On-Demand Advanced (Cont.) var bars = chart.selectAll(“g”) … .on(“mouseover”, function(d,i){ d3.select(this).select(“rect”).attr(“fill”, “orange”); d3.select(this).select(“text”).attr(“display”, null); }) .on(“mouseleave”, function(d,i){ d3.select(this).select(“rect”).attr(“fill”, null); d3.select(this).select(“text”).attr(“display”, “none”); });
  88. 88. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions • Substitute the group selection code. 88 Tutorial 12. Details-On-Demand Advanced (Cont.) var bars = chart.selectAll(“g”) … .on(“mouseover”, function(d,i){ d3.select(this).select(“rect”).attr(“fill”, “orange”); d3.select(this).select(“text”).attr(“display”, null); }) .on(“mouseleave”, function(d,i){ d3.select(this).select(“rect”).attr(“fill”, null); d3.select(this).select(“text”).attr(“display”, “none”); }); <group> Null assigns ‘default value’
  89. 89. Course | Young-Ho Kim – A Quick and Dirty D3.js Interactions • Now the ticks shows only when hovering. 89 Tutorial 12. Details-On-Demand Advanced (Cont.)
  90. 90. Transitions
  91. 91. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • Technically, transitions are smoothly changing the visuals by interpolating geometric properties. 91 Benefits of Incorporating Transitions Jeffrey Heer, George Robertson. 2007. Animated Transitions in Statistical Data Graphics
  92. 92. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • Interpolating the elements can orient user to keep perception of change – Useful for refreshing chart. • Aesthetically pleasing. 92 Benefits of Incorporating Transitions (Cont.)
  93. 93. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • In D3, a transition is a special type of selection. • Attributes and style assignment applies over time. 93 Transitions in D3 selection.transition() • Transition object has 3 main properties: • transition.duration(millis) : specifies per-element duration in milliseconds. The parameter can be a function(d,i). • transition.delay(millis) : the transition starts after the delay. The parameter can be a function(d,i).
  94. 94. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions 94 Transitions in D3 (Cont.) transition.ease(“method”) Specifies the transition easing function. The parameter can be a function(t), or a predefined string constant. D3.js Easing Checker
  95. 95. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • Let’s make your bars appear smoothly. • Animate the bar width from 0 to target width. • First, set the initial width of rect as Zero. 95 Tutorial 13. Smooth Emerging bars.append(“rect”) .attr(“width”, 0) .attr(“height”, barHeight)
  96. 96. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • Then derive a transition from the selection. • Assign duration and the target attributes. • Easing is optional. Try other easing functions, too. 96 Tutorial 13. Smooth Emerging (Cont.) bars.append(“rect”) .attr(“width”, 0) .attr(“height”, barHeight) .transition() .duration(750) .ease(“cubic-out”) .attr(“width”, function(d){return x(d.value)});
  97. 97. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • We learned that the delay function allows a function as a paremeter. Let’s make our bars emerge sequentially. 97 Tutorial 13. Smooth Emerging (Cont.) bars.append(“rect”) .attr(“width”, 0) .attr(“height”, barHeight) .transition() .duration(750) .delay(function(d,i){ return i * 100 }) .ease(“cubic-out”) .attr(“width”, function(d){return x(d.value)});
  98. 98. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • Transitions can be used in event handlers. 98 Tutorial 13. Smooth Emerging (Cont.) on("mouseover", function(d,i){ d3.select(this).select("rect") .transition().duration(300).ease("cubic-out") .attr("fill", "orange"); d3.select(this).select("text").attr("display", null); }) .on("mouseleave", function(d,i){ d3.select(this).select("rect") .transition().duration(200).attr("fill", null);
  99. 99. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • Transition is powerful for interpolating between the two states of visualization. • D3’s AJAX data loading enables refreshing chart by applying different data to the same chart. • By combination of transition and joins, we can easily refresh our visualization. 99 Transition between Data
  100. 100. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • Transition between data is one of the major power of D3. • In this final tutorial, we will make our visualization switch between different dataset, SMOOTHLY. 100 Tutorial 14. Transition between Data
  101. 101. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • We will change the dataset. • data2.json • Containing two tables in an array. • Names in the second table is a subset of the first one, but the values are different. 101 Tutorial 14. Transition between Data (Cont.)
  102. 102. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • First, we need a button to shuffle. • Add <button> element inside the body. • Assign onClick event handler. • We will define shuffle() later. 102 Tutorial 14. Transition between Data (Cont.) <body> <button onClick="shuffle()">Shuffle</button> …
  103. 103. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • Pull out the declaration of variables that should be consistent during runtime. • Variables declared inside the d3.json() callback cannot be accessed outside. 103 Tutorial 14. Transition between Data (Cont.) <script> var padding = {left:80, top:0, right:30, bottom:50}; var chartWidth = 500 - padding.left - padding.right; var chartHeight = 500 - padding.top - padding.bottom; …
  104. 104. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions • Scales and axis functions are also reused during runtime. • Y axis ticks should be changed so we don’t assign domain() here. 104 Tutorial 14. Transition between Data (Cont.) … var chartHeight = 500 - padding.top - padding.bottom; var x = d3.scale.linear().domain([0, 100]).range([0, chartWidth]); var xAxis = d3.svg.axis().orient("bottom").scale(x); var y = d3.scale.ordinal().rangeBands([0, chartHeight]); var yAxis = d3.svg.axis().orient("left").scale(y);
  105. 105. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions Pull out the chart canvas too. The SVG must be appended only once. 105 Tutorial 14. Transition between Data (Cont.) … var yAxis = d3.svg.axis().orient("left").scale(y); var chart = d3.select("body") .append("svg").attr({width:500, height:500}) .append("g") .attr("transform", "translate(" + padding.left + ",“ + padding.top + ")");
  106. 106. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions We also need the axis groups be appended only once. 106 Tutorial 14. Transition between Data (Cont.) var chart = … chart.append("g").attr("class", "x axis") .attr("transform", "translate(0," + chartHeight + ")") .call(xAxis); chart.append("g").attr("class", "y axis") .call(yAxis);
  107. 107. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions All we need to do when the data loading is finished is to send the reference of loaded data to global scope. Do not forget to change the file name to “data2.json”. 107 Tutorial 14. Transition between Data (Cont.) var data; d3.json("data2.json", function(error, json){ if(json!=null){ data = json; } });
  108. 108. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions Next, we need to make routines to build final chart based on the data. In the routine, focus on what elements would change according to the data. First, the Y-axis should be refreshed. 108 Tutorial 14. Transition between Data (Cont.) function refresh(data){ y.domain(data.map(function(d){return d.name})); chart.select(".y.axis") .transition().duration(500).call(yAxis);
  109. 109. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions This is the point. Remember the three joins in selection? Memorize the order ‘Enter-Update-Exit’. Handling joins is one of the most challenging part in D3. Let’s start from initializing update selection by data() function. 109 Tutorial 14. Transition between Data (Cont.) var bars = chart.selectAll("g.bar") .data(data);
  110. 110. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions Handling Enter selection – You initialize the new things. The code is almost the same as before. 110 Tutorial 14. Transition between Data (Cont.) var new_bars = bars.enter() .append("g") .attr("class", "bar") … new_bars.append("rect") … new_bars.append("text") …
  111. 111. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions Handling Update selection – Think about what properties should be modified(or updated). First, the height of bars could be changed because it is derived by the number of data rows. The Y position of bars could be changed, too. 111 Tutorial 14. Transition between Data (Cont.) var barHeight = chartHeight/data.length - 2; bars.transition().duration(500) .attr("transform", function(d){return "translate(0," +y(d.name)+")"});
  112. 112. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions A <rect> and a <text> elements in each group need to be updated. 112 Tutorial 14. Transition between Data (Cont.) bars.select("rect") .transition().duration(500) .delay(function(d,i){return i*100}) .attr("width", function(d){return x(d.value)}) .attr("height", barHeight); bars.select("text") .transition().duration(500) .delay(function(d,i){return i*100}) .attr("x", function(d){return x(d.value) - 5}) .attr("y", barHeight/2) .text(function(d){return d.value});
  113. 113. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions Handling Exit selection – Remove the elements properly. You don’t need to care about rects and texts, because they will be removed with their parent group. The remove() function will remove the bars after the transition finishes. 113 Tutorial 14. Transition between Data (Cont.) bars.exit() .transition().duration(250) .style("opacity",0) .remove(); }//end of refresh(data)
  114. 114. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions Finally, prepare shuffle() function on the outmost scope. 114 Tutorial 14. Transition between Data (Cont.) … }//end of refresh(data) var currentIndex = 0; function shuffle() { currentIndex = (++currentIndex)%2; refresh(data[currentIndex]); }
  115. 115. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions Good job. Your chart will be refreshed smoothly. 115 Tutorial 14. Transition between Data (Cont.)
  116. 116. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions One more important thing. This is the true difference of the two tables. 116 Tutorial 14. Transition between Data (Cont.)
  117. 117. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions But your visualization pairs the rows like this. 117 Tutorial 14. Transition between Data (Cont.)
  118. 118. Course | Young-Ho Kim – A Quick and Dirty D3.js Transitions This mapping causes the transition not to be meaningful, because the transition doesn’t show the implicit change of the data. But don’t worry. D3 solves this mapping problem easily. Specify the second parameter of the data() function. 118 Tutorial 14. Transition between Data (Cont.) var bars = chart.selectAll("g.bar") .data(data, function(d){return d.name});
  119. 119. Course | Young-Ho Kim – A Quick and Dirty D3.js When D3 matches the old data and the new data in the element, it compares the keys derived from the parameter function. In this case, D3 will consider the two data points with the same name field to be paired. Transitions 119 Tutorial 14. Transition between Data (Cont.) var bars = chart.selectAll("g.bar") .data(data, function(d){return d.name});
  120. 120. Other Features of D3 Which we didn’t cover today
  121. 121. Course | Young-Ho Kim – A Quick and Dirty D3.js Other Features of D3 D3 provide brushing components with predefined interaction. https://github.com/mbostock/d3/wiki/SVG-Controls http://bl.ocks.org/mbostock/1667367 http://bl.ocks.org/mbostock/4063663 121 Brushing
  122. 122. Course | Young-Ho Kim – A Quick and Dirty D3.js Other Features of D3 Requires D3-tip library https://github.com/caged/d3-tip http://bl.ocks.org/Caged/6476579 122 Tooltips
  123. 123. Course | Young-Ho Kim – A Quick and Dirty D3.js Other Features of D3 • Using tickFormat() function on scales, You can specify the format of the tick labels. • http://bl.ocks.org/mbostock/9764126 123 Formatting Axis Ticks
  124. 124. Tips
  125. 125. Course | Young-Ho Kim – A Quick and Dirty D3.js Tips • JavaScript is a powerful language, but using D3, you will see your code gets too long. • CoffeeScript is a little language that compiles into pure JavaScript in one-to-one mappings. http://coffeescript.org/ • Using it instead of pure JavaScript will significantly reduce the amount of your code. 125 Learn Simplified JavaScript Descendants .attr(“width”, function(d){return x(d.value)}) .attr “width”, (d)->x(d.value)
  126. 126. Course | Young-Ho Kim – A Quick and Dirty D3.js Tips • There are plenty of tutorials and questions by Bostock and other gurus on web. • Most of the barriers you met are already dealt with before in stackoverflow.com. 126 Learn by Plenty of Tutorials and Questions bl.ocks.org stackoverflow
  127. 127. Course | Young-Ho Kim – A Quick and Dirty D3.js Tips • Although JavaScript and D3 make it look interactive, SVG is merely a static vector image defined by markups. • Svg code can be saved in a *.svg file and modified in Adobe Illustrator. • Good for building figures of chart which is not supported by canonical tools such as R or Excel. 127 D3 Chart Can Be Used Elsewhere.
  128. 128. Course | Young-Ho Kim – A Quick and Dirty D3.js Tips • D3’s asynchronous data loading is good for visualizing dynamic data. • If you are using D3 on your website with database, you can attach D3 visualization with data pulled from your database. 128 Learn ways to Dynamically Generating Web Server Database Client Server URL from d3.json parameter Generate JSON from Database Visualize Server-side Data
  129. 129. Course | Young-Ho Kim – A Quick and Dirty D3.js Tips • Server Frameworks based on interpreter languages are convenient for data preparation. Most of them are designed to easily handle data structure. Ruby On Rails (Ruby), Django(Python), … • Also, most of them are incorporating database. 129 Learn ways to Dynamically Generating (Cont.)
  130. 130. Course | Young-Ho Kim – A Quick and Dirty D3.js Tips • Building a complete visualization with pure D3 from scratch is a real pain. • If you are not designing your original visualization, try using other projects wrapping D3 or substituting D3. C3.js, Dimple, MetricsGraphics, …. 130 Do not Keep Your Eyes only on D3
  131. 131. Thank You! Any Questions? 131

×