D3.js is a low-level data visualisation library. For a high-level JavaScript library, use observable plot.

loading data

d3.csv(url) // returns a promise object (asynchronous operation)
  .then(...) // fulfil the promise
 
d3.json(url)  // does not support row conversion functions

or within Observable notebook

data = await FileAttachment(url).csv({typed: true})

data manipulation

  • filter. data.filter((d) => (d.Year === 2002) | (d.Year === 2019))
  • grouping (by multiple columns). grouped = d3.group(data_filtered, (d) => d.Sex, (d) => d.Year)
    • returns a Map from key to array of value (or, using groups, an array of [key, value] entries)
  • array manipulation

data joins

  • D3 selections let you choose some HTML or SVG elements and change their style and/or attributes
    • d3.select selects the first matching element
    • d3.selectAll selects all matching elements
  • Data join
    • join an array of data to a D3 selection using following 4-stage (select, data, join, attr/style) pattern:
let array = [40, 10, 20, 60, 30];
 
d3.select(".chart") // CSS selector string, single element
  .selectAll("circle") // string describing the type of element
  .data(array) // defines the array that's being joined
  .join("circle") // HTML or SVG elements are added and removed
  // then add .attr and .style to HTML/SVG elements
  // data driven function with joined-value, d, and index, i
  .attr("cx", (d, i) => i * 100) // circle x axis
  .attr("cy", 50)
  .attr("r", (d) => 0.5 * d) // circle radius
  .style("fill", (d) => d > 30 ? 'orange' : "#eee"); // fill circles with different colours

shapes

D3 provides functions for drawing shapes:

  • d3.line. draw lines between points , add curve .curve(d3.curveCardinal) to interpolate null
  • d3.area. area between y=0 and line
  • d3.stack. stacked bar

scales and axes

  • scale functions:
    • continuous:
      • linear (scaleLinear)
      • square root (scaleSqrt)
      • log (scaleLog)
      • time (scaleTime, domain is expressed as an array of dates)
    • continuous input to discrete output (scaleQuantize, scaleThreshold)
    • discrete input to discrete output (scaleOrdinal)
  • d3.extent(data) find domain and .nice() to round values
// scale function
scaleFunction(
	input  // usually a number, date or category
)  // -> value, such as a coordinate, a colour, a length or a radius
// e.g.
let myScale = d3.scaleLinear()
  .domain([0, 10])
  .range([0, 600]);
 
myScale(0);   // returns 0
myScale(2);   // returns 120
myScale(3);   // returns 180
...
myScale(10);  // returns 600
  • make an axis generator function using d3.axisBottomd3.axisTopd3.axisLeft or d3.axisRight (and pass in your scale function)
  • format using axis.ticks or axis.tickValues
plots
  .append("g")
  .attr("transform", "translate(" + [0, height] + ")")
  .call(
    d3.axisBottom(myScale)  // axis generator function
    .ticks(0)  // formatting, in this case remove ticks
  );

maps

  • GeoJSON. JSON-based format for specifying geographic data.
  • projections. functions that convert from latitude/longitude [lon, lat] -> [x, y] .
  • geographic path generators (e.g. d3.geoPath, d3.geoCicle). functions (shape generator) that convert GeoJSON shapes into SVG paths.

interaction and animation

  • interaction
    • d3.handleMousemove for hovering
      • for smaller items, use quadtree or Delaunay triangulation to find the nearest point
    • d3.drag to move items
    • d3.brush for specifying an area
let zoom = d3.zoom()
  .on("zoom", handleZoom);
 
function initZoom() {
  d3.select("svg").call(zoom);
}
 
...
initZoom()
  • transition
    • add a .transition() call before the .attr and .style methods that you wish to transition
    • .duration(2000) in milliseconds and .delay(20), which can also accept a function to stagger delays
    • easing function (e.g. .ease(d3.easeBounceOut)) defines the change in speed of an element during a transition
    • transitions can be chained together by adding multiple calls to .transition
    • customise the path the elements take using a .tween() function
    • enter, exit, and update functions are required for fine-grained control of transitioning elements
      • entering elements are newly created elements
      • exiting elements are elements that are about to be removed

other