Getting Started With d3.js
@delainewendling
Delaine Wendling
What is d3.js?
D3 (Data-Driven Documents or D3.js) is a JavaScript library for visualizing data
Goals of this Talk
- Explain why data visualizations are powerful
- Compare different data libraries and their respective advantages and disadvantages
- Become more familiar with d3 syntax and patterns so that its numerous examples are less intimidating
- Create a few charts
Where and why are data visualizations used?
Google Forms
Mint.com
The government
What's out there?
ChartJs - supports 6 different chart styles.
Dygraphs - supports line charts and can handle a lot of data.
ZingChart - supports multiple charts, has very few customization options.
Google Charts - supports multiple chart options.
*High Charts and Fusion Charts are only free for non-commercial use
PROS
CONS
Highly customizable
Steep learning curve
Lightweight
Large community with a lot of examples for inspiration
IE 6-8 not supported
Many projects built on top of d3 (NVD3, crossfilter, DC)
Chart export
Label Management
Why d3.js?
Why do we even need a visualization library?
ENTER
EXIT
EXIT
Update
ENTER
UPDATE
<div class="chart">
<img>
<img>
</div>
HTML
const dataArr = [
{id: 1, alive: true, img: "http://bit.ly/romeo_character"},
{id: 2, alive: true, img:"http://bit.ly/juliet_character"}];
let chart = d3.select(".chart");
let selection = chart.selectAll("img")
.data(dataArr)
.attr("src", d => d.img)
.style({left: (d, i) => i*110 + "px"});
JavaScript
ENTER
<div class="chart">
<img>
<img>
</div>
HTML
let dataArr = [
{id: 1, alive: true, img: "http://bit.ly/romeo_character"},
{id: 2, alive: true, img:"http://bit.ly/juliet_character"}];
dataArr = [...dataArr,
{id: 3, alive: true, img: "http://bit.ly/lordcapulet_character"},
{id: 4, alive: true, img:"http://bit.ly/ladycapulet_character"}];
let chart = d3.select(".chart");
let selection = chart.selectAll("img")
.data(dataArr)
selection.attr("src", d => d.img)
.style({left: (d, i) => i*110 + "px"});
selection.enter().append("img")
.attr("src", d => d.img)
.style({left: (d, i) => i*110 + "px"});
JavaScript
<div class="chart"></div>
HTML
const dataArr = [
{id: 1, alive: true, img: "http://bit.ly/romeo_character"},
{id: 2, alive: true, img:"http://bit.ly/juliet_character"}];
function createPlay(data){
let chart = d3.select(".chart");
let selection = chart.selectAll("img")
.data(data)
selection.enter().append("img")
.attr("src", d => d.img)
.style({left: (d, i) => i*110 + "px"});
}
createPlay(dataArr);
const newData = [...dataArr,
{id: 3, alive: true, img: "http://bit.ly/lordcapulet_character"},
{id: 4, alive: true, img:"http://bit.ly/ladycapulet_character"}];
createPlay(newData);
JavaScript
EXIT
EXIT
const dataArr = [
{id: 1, alive: true, img: "http://bit.ly/romeo_character"},
{id: 2, alive: true, img:"http://bit.ly/juliet_character"},
{id: 3, alive: true, img: "http://bit.ly/lordcapulet_character"},
{id: 4, alive: true, img:"http://bit.ly/ladycapulet_character"}];
function createPlay(data){
let chart = d3.select(".chart");
let selection = chart.selectAll("img")
.data(data)
selection.enter().append("img")
.attr("src", d => d.img)
.style({left: (d, i) => i*110 + "px"});
selection.exit().remove();
}
createPlay(dataArr);
const newData = dataArr.filter(d => +d.id === 2);
createPlay(newData);
EXIT
EXIT
Existing
New Data
const dataArr = [
{id: 1, alive: true, img: "http://bit.ly/romeo_character"},
{id: 2, alive: true, img:"http://bit.ly/juliet_character"},
{id: 3, alive: true, img: "http://bit.ly/lordcapulet_character"},
{id: 4, alive: true, img:"http://bit.ly/ladycapulet_character"}];
function createPlay(data){
let chart = d3.select(".chart");
let selection = chart.selectAll("img")
.data(data, d => +d.id)
selection.enter().append("img")
.attr("src", d => d.img)
.style({left: (d, i) => i*110 + "px"});
selection.exit().remove();
}
createPlay(dataArr);
const newData = dataArr.filter(d => +d.id === 2);
createPlay(newData);
Existing
New Data
Update
const dataArr = [
{id: 2, alive: true, img:"http://bit.ly/juliet_character"}];
function createPlay(data){
let chart = d3.select(".chart");
let selection = chart.selectAll("img")
.data(data, d => d.img)
selection.enter().append("img")
.attr("src", d => d.img)
.style({left: (d, i) => i*110 + "px"});
selection.exit().remove();
}
createPlay(dataArr);
const newData = dataArr.map(character => {
return {...character,
img: "http://bit.ly/julietdead_character"}
});
createPlay(newData);
ENTER
const dataArr = [
{id: 2, alive: false, img: "http://bit.ly/julietdead_character"}];
function createPlay(data){
let chart = d3.select(".chart");
let selection = chart.selectAll("img")
.data(data, d => d.img)
selection.enter().append("img")
.attr("src", d => d.img)
.style({left: (d, i) => i*110 + "px"});
selection.exit().remove();
}
createPlay(dataArr);
const newData = [...dataArr, {id:1, alive: true,
img:"https://bit.ly/romeo_character"}];
createPlay(newData);
UPDATE
const dataArr = [{id:1, alive: true, img:"https://bit.ly/romeo_character"},
{id: 2, alive: false, img: "http://bit.ly/julietdead_character"}];
function createPlay(data){
let chart = d3.select(".chart");
let selection = chart.selectAll("img")
.data(data, d => d.img)
selection.enter().append("img")
.attr("src", d => d.img)
.style({left: (d, i) => i*110 + "px"});
selection.exit().remove();
}
createPlay(dataArr);
const newData = dataArr.map(character => {
return character.id == 1 ? {...character, alive: false,
img: "http://bit.ly/romeodead_character"} : character
});
createPlay(newData);
Let's Review
SVG
<svg>
<rect x="25" y="25" width="200" height="200"
fill="lime" stroke-width="4" stroke="pink" />
<circle cx="125" cy="125" r="75" fill="orange" />
<polyline points="50,150 50,200 200,200 200,100"
stroke="red" stroke-width="4" fill="none" />
<line x1="50" y1="50" x2="200" y2="200"
stroke="blue" stroke-width="4" />
</svg>
SVG
SVG
SVG
Object Constancy
"Animation should only be used when it enhances understanding"
Object Constancy Examples
Technology Bubble Chart: https://naustud.io/tech-stack/
What makes us happy: http://charts.animateddata.co.uk/whatmakesushappy/
What kills us: https://www.infino.me/mortality/usmap
Conclusion
Choose the best tool for the job
Leverage the examples and community available to you
Resources
Make a bar Chart (3 parts): https://bost.ocks.org/mike/bar/
Thinking with Joins: https://bost.ocks.org/mike/join/
The General Update Pattern: https://bl.ocks.org/mbostock/3808218
Resources
More on the data join: https://medium.com/@c_behrens/enter-update-exit-6cafc6014c36
Comparing Libraries: https://www.sitepoint.com/javascript-charting-library-main-contenders/
Gallery of D3 examples: https://github.com/d3/d3/wiki/Gallery
Questions?
deck
By Delaine Wendling
deck
- 1,641