Transcript
A Quick & Dirty D3.js
Young-Ho KimHuman-Computer Interaction Lab
Dept. of Computer Science & Engineering
Seoul National University
Course
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
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
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
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?
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
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
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
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
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
Course | Young-Ho Kim – A Quick and Dirty D3.js
Tutorial
Lets use D3.js!
Tutorial 1. Prepare to use D3
11
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.)
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.)
Data Preparation
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
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
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
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
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
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.
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}
});
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);
}
});
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.
Basic Drawing
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
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.
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”);
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.
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
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
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
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.
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.)
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
}
});
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”);
}
}
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.
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
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.
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});
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
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
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>
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)
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)
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
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});
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.
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.)
Advanced Chart Drawing
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.
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
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.)
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.)
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});
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
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
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
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
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.
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.
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);
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 + “)”);
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);
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)});
Course | Young-Ho Kim – A Quick and Dirty D3.js
Advanced Chart Drawing
• Now you have axes.
65
Tutorial 8. Employing Axis (Cont.)
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 100 120 140
<path class=“domain” … >
<g class=“tick” … >A tick and a value text are grouped.
<line … >
<text … >
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;
}
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;
}
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>
…
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
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”)
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
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.
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
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
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
Interaction
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
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){})
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
});
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
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);
});
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
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
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});
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);
});
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”);
});
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’
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.)
Transitions
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
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.)
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).
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
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)
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)});
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)});
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);
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
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
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.)
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>…
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;…
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);
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 + ")");
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);
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;}
});
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);
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);
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")…
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)+")"});
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});
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)
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]);
}
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.)
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.)
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.)
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});
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});
Other Features of D3
Which we didn’t cover today
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
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
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
Tips
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)
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
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.
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
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.)
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
Thank You!
Any Questions?
131
top related