
Dress up your Data: an Introduction to D3.js

6:00 - 6:20 Food & Networking
6:20 - 7:20 Presentation
WIFI: Kenzan Guest
p: welcometokenzan

Dress up your Data: an Introduction to D3.js
Tim Mendoza
Front End Developer

What is D3.js?
- Data-driven documents
- A collection of JavaScript modules
- Modify document (DOM) attributes based on data

- Expressive
- Large diversity of possible visualizations
What's cool about D3.js
- It sits on top of web standards
- Declarative API
- Transparent, easy to debug

What's not so cool about D3.js
- Requires good working knowledge of HTML, CSS, SVG, and JavaScript (but learning about this is cool!)
- Steeper learning curve
- Takes more time to implement

SVG Basics
<svg width="400" height="250">
<g transform="translate(10, -5)">
<line x1="50" y1="75" x2="150" y2="200" stroke="red"></line>
<rect x="175" y="30" width="40" height="125" fill="green" stroke="black" stroke-width="1"></rect>
<rect x="250" y="30" width="40" height="125" fill="green" stroke="black" stroke-width="20"></rect>
<circle cx="150" cy="130" r="45" fill="transparent" stroke="blue" stroke-width="15"></circle>
<path
d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80"
stroke="orange"
fill="transparent"
transform="translate(170, 50)"
/>
<text x="240" y="200">Text!!</text>
<foreignObject x="180" y="180">
<span>Span!!</span>
</foreignObject>
</g>
</svg>

SVG Coordinates
<svg width="600" height="300"> </svg>
(0, 0)
(600, 0)
(0, 300)
(0, 0)
<g transform="translate(300, 150)">
</g>
+
+

<svg>
<rect></rect>
<rect></rect>
<rect></rect>
<rect></rect>
<rect></rect>
</svg>
var rects = document.querySelectorAll('rect')
rects.forEach((rect, i) => {
rect.setAttribute('x', 0)
rect.setAttribute('y', i * 20)
rect.setAttribute('width', (i + 1) * 30)
rect.setAttribute('height', 20)
rect.setAttribute('stroke', 'white')
})$('rect')
.attr('x', 0)
.attr('y', i => i * 20)
.attr('width', i => (i + 1) * 30)
.attr('height', 20)
.attr('stroke', 'white')d3.selectAll('rect')
.attr('x', 0)
.attr('y', (d, i) => i * 20)
.attr('width', (d, i) => (i + 1) * 30)
.attr('height', 20)
.attr('stroke', 'white')Vanilla:
jQuery:
d3.js:
DOM Manipulation

DOM Manipulation - with data!
// Select first matching element
d3.select('.mySelector');
// Select all matching elements
d3.selectAll('.mySelectors');selection.selectAll('.newSelector');
selection.select('.newSelector');
selection.data(someArray);
selection.filter(d => d.value > 100);
selection.merge(otherSelection);
selection.attr('x', d => d.value);
selection.style('opacity', d => d.confidence);
selection.text(d => d.name);
selection.classed('isVisible', d => d.isVisible);
selection.on('click', function(d) { ... });
selection.property('checked', d => d.checked);
selection.html('<span></span>')
selection.append('rect')
selection.remove()
d3-selection
Selections
Operators


The Data Join
const rects = d3.selectAll('rect').data([1, 2, 3]);
// Update
rects
// Enter
rects.enter()
// Exit
rects.exit()
const circles = d3.selectAll('circle').data(data);
// Update
circles
.attr('r', d => d.radius)
// Enter
circles
.enter()
.append('circle')
.attr('r', d => d.radius)
.attr('cx', d => d.x)
.attr('cy', d => d.y);
// Exit
circles
.exit()
.remove()General Update Pattern

d3 Module Ecosystem
d3-array
d3-axis
d3-brush
d3-chord
d3-collection
d3-color
d3-contour
d3-dispatch
d3-drag
d3-dsv
d3-ease
d3-fetch
d3-force
d3-format
d3-geo
d3-geo-polygon
d3-geo-projection
d3-hierarchy
d3-interpolate
d3-path
d3-polygon
d3-quadtree
d3-random
d3-sankey
d3-scale
d3-scale-chromatic
d3-selection
d3-shape
d3-time
d3-time-format
d3-timer
d3-transition
d3-voronoi
d3-zoom

d3-scale

32ºF
90ºF
600px
0px
let xScale = d3.scaleLinear()
.domain([32, 90])
.range([0, 600]);xScale(32) // 0
xScale(60) // 289.65
xScale.invert(600) // 90
xScale.invert(450) // 75.5

d3-axis
d3-axis + d3-zoom
How to build a bar chart
Start Simple
Add data
Add scale
Apply general update pattern
Add axes
Add transitions
Connect to real data
d3-force

Forces are additive
Forces can display trees
Testing
- Unit tests
- Jest snapshots with JSDOM
- Behavior testing with Cypress
- Manual testing

Jest snapshots
exports[`the d3 drawAngleGrid function should render the grid for the angle axis 1`] = `
<g>
<line
transform="translate(0, 0)"
x2="375"
y2="0"
/>
<line
transform="translate(0, 0)"
x2="2.2962127484012872e-14"
y2="375"
/>
<line
transform="translate(0, 0)"
x2="-375"
y2="4.5924254968025744e-14"
/>
<line
transform="translate(0, 0)"
x2="-6.888638245203861e-14"
y2="-375"
/>
</g>
`;
Jest snapshots
The good:
- Easy to verify many values at once
The bad:
- Tests fail if snapshots change
- Failing tests provide valuable diffs
- Have to manually verify on first run
- Cumbersome to verify large snapshots
- Must structure code to render small snapshots
- Can't test user interactions

- 'SVGElement' is not implemented in JSDOM
Cypress
The good:
- Very easy to write tests
The bad:
- Can see tests run in Chrome (good for visualizations)
- Mock API calls
- Chrome only (more browsers on the way soon!)
- Assert against outgoing network calls
- Can run tests in CLI or CI/CD
- Have direct access to DOM in tests

- Immediate feedback
Cypress
- Test behaviors, not code



How to actually use D3.js
- Google stuff!
- Look at examples
- https://bl.ocks.org/mbostock
- “Immature poets imitate; mature poets steal" -T.S. Elliot

- D3.js documentation
- Source code

How to gain insight from your data?



Thank you!
Useful links (take a picture)
timmydoza@gmail.com -email me!
-Mike Bostock's d3 examples
-Mike Bostock's blog
-These slides
-Spotify demo
-SVG Tutorial
Intro to D3.js
By Tim Mendoza
Intro to D3.js
- 658