# An intro to D3.js

Maarten Lambrechts

INEGI

CIMAT

15 October 2021

# Course outline

## Last week

Webdev 101

D3.js?

A bubble chart with D3, part 1

# Exercise: scale and fill circles, logarithmic scale

Scale circles with d3.scaleSqrt()

jsbin.com/coxefax/9/edit

Convert X scale to a logarithmic scale with d3.scaleLog()

jsbin.com/coxefax/10/edit

Add a color scale to fill by continent with d3.scaleOrdinal()

jsbin.com/coxefax/11/edit

# Sort data

Sort data to show small bubbles on top

No D3, just "vanilla" javascript

``````data.sort(function(a,b){
return b.population - a.population;
})``````

# Exercise: sort data

Sort the data (also try to revert the sorting)

jsbin.com/coxefax/14/edit

Transform

d3.axisBottom()

d3.axisLeft()

# Exercise: margins convention, x and y axes

Refactor to implement the margins convention

jsbin.com/coxefax/14/edit

# Customise axis

Custom tick values

Use ticks to make a grid

``````const xAxis = d3.axisBottom(xScale)
.tickValues([500, 1000, 2000, 4000, 8000, 16000, 32000, 64000])
.tickFormat(d3.format(".1s"))
.tickSizeInner(-height);``````

# Exercise: grid and text annotation

Add grid with negative inner tick size and css for colors, add tick values for the xAxis

jsbin.com/coxefax/18/edit

Text annotation for the year

jsbin.com/coxefax/19/edit

# Tooltips

css for styling

``````div.tooltip {
position: absolute;
text-align: center;
height: 24px;
font: 18px sans-serif;
background: white;
border: 2px solid black;
pointer-events: none;
}``````
``````const tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);``````

Add a div for the tooltip

Hide it by setting its opacity to 0

# Tooltips

Add event listeners on the bubbles with .on()

Show the tooltip and set its content on mouseover, hide the tooltip on mouseout

``````.on("mouseover", (event,d) => {
tooltip.style("opacity", 1)
.text(d.country)
.style("left", (d3.pointer(event)[0] + 10) + "px")
.style("top", (d3.pointer(event)[1]+50) + "px");
})
.on("mouseout", (d) => {
tooltip.style("opacity", 0);
});``````

# Exercise: tooltips

Add a div, css and event listeners for the tooltip

jsbin.com/mosudux/4/edit

# Exercise: 1960 data

jsbin.com/mosudux/6/edit

# Toggle

Add event listener to detect changes

``````d3.selectAll('input').on('change', function() {
console.log('selection changed to ' + this.value);
});``````
``````<form>
<input type="radio" name="year" value="2018" checked> 2018<br>
</form>``````

Html input elements

# Exercise: data toggle

jsbin.com/mosudux/8/edit

# Transitions

``````d3.selectAll("circle").transition()
.duration(1500)
.attr("cx", (d) => xScale(d.income60))
.attr("cy", (d) => yScale(d.lifeexp60))
.attr("r", (d) => rScale(d.population60))
}``````

Update attributes and use .transition() to animate

# Exercise: transition

jsbin.com/coxefax/27/edit

# Exercise: change the year annotation

Change the content of the year annotation when the toggle is clicked

jsbin.com/coxefax/29/edit

# Modules and packages

Import and export javascript modules

``````import { axisLeft, axisRight } from 'd3-axis'
import { scaleLinear, scaleLog, scaleSqrt } from 'd3-scale'``````

# npm

Node package manager

``npm install d3-scale d3-axis --save``

# Frontend frameworks

Take control of the DOM, decide what is rendered => d3.select(), d3.selectAll()

Manage state

Boiler plates to get started

``````<svg width={width} height={height}>
<g className="bubbles-g">
{countries.map((d) => {
return (
<circle
key={"bubble-" + d.Country}
cx={xScale(d.coosshare)}
cy={yScale(d.bmpshare)}
r={sizeScale(d.total)}
fill={colorScale(d.Region)}
stroke={
activeCountry === ""
? highlightcountries.length === 0
? "white"
: highlightcountries.includes(d.Country)
? "black"
: "white"
: d.Country === activeCountry
? "black"
: "white"
}
strokeWidth={...}
style={{ cursor: "pointer" }}
opacity={...}
onMouseOver={() => {//Show tooltip}}
onMouseLeave={() => {//Hide tooltip}}
></circle>
</g>
</svg>``````

By maartenzam

• 1,757