Maarten Lambrechts
INEGI
CIMAT
15 October 2021
Webdev 101
D3.js?
A bubble chart with D3, part 1
Scale circles with d3.scaleSqrt()
Convert X scale to a logarithmic scale with d3.scaleLog()
Add a color scale to fill by continent with d3.scaleOrdinal()
Sort data to show small bubbles on top
No D3, just "vanilla" javascript
data.sort(function(a,b){
  return b.population - a.population;
})Sort the data (also try to revert the sorting)
Add a <g> element
Transform
Adjust scales
d3.axisBottom()
d3.axisLeft()
Refactor to implement the margins convention
Add axes
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);Add grid with negative inner tick size and css for colors, add tick values for the xAxis
Text annotation for the year
css for styling
div.tooltip {	
    position: absolute;			
    text-align: center;								
    height: 24px;
    padding: 5px;				
    font: 18px sans-serif;		
    background: white;	
    border: 2px solid black;		
    border-radius: 8px;			
    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
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);
});Add a div, css and event listeners for the tooltip
Add data for 1960
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="1960"> 1960<br>
  <input type="radio" name="year" value="2018" checked> 2018<br>
</form>Html input elements
Add radio buttons to toggle the data
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
Add the transitions
Change the content of the year annotation when the toggle is clicked
Import and export javascript modules
import { axisLeft, axisRight } from 'd3-axis'
import { scaleLinear, scaleLog, scaleSqrt } from 'd3-scale'Node package manager
npm install d3-scale d3-axis --saveTake 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>