Skip to content
Back to Blog
Article Platform
Field Notes
Long Form

D3 Tutorial

An interactive introduction to how D3.js works with SVG elements, data joins, charts, and maps.

Dispatch

6 min read
Reading Track Article Notes
Code, Math, Long Form

D3 Tutorial

Working with Javascript

We have the following data of cars

List of Cars

Code
[
  {
    "make": "Nissan",
    "model": "Leaf",
    "year": 2012,
    "price": 1800
  },
  {
    "make": "Ford",
    "model": "F150",
    "year": 2009,
    "price": 1950
  },
  {
    "make": "Chevrolet",
    "model": "Trailblazer",
    "year": 2009,
    "price": 2100
  },
  {
    "make": "Tesla",
    "model": "ModelX",
    "year": 2012,
    "price": 100000
  }
]

We can use functional programming to make it look nicer. The code below use a functional paradigm. By making a reduce function we can easily format json formatted data.

Code
data.reduce((acc, d) => {
  acc += formatCar(d) + "\n";
  return acc;
}, "");
export const formatCar = (car) =>
  `${car.year} ${car.make} ${car.model}: ${car.price}`;

Output:

Code
/*
2012 Nissan Leaf: 1800
2009 Ford F150: 1950
2009 Chevrolet Trailblazer: 2100
2012 Tesla ModelX: 100000
*/

This is done by mapping over the data with a custom function that formats each object (i.e. each car description). Look at components/car.js file for the formatting function.

We can also filter by a specific price. In the following example we filter by car prices less than $2000.

Code
export const filterByPrice = (cars, price) =>
  cars.filter((car) => car.price < price);

Result of applying the filter method used here

Code
[
  {
    "make": "Nissan",
    "model": "Leaf",
    "year": 2012,
    "price": 1800
  },
  {
    "make": "Ford",
    "model": "F150",
    "year": 2009,
    "price": 1950
  }
]

HTML CSS and SVG

We can write scalable vector graphics (SVG) using the svg tag. Learn the follwoing:

  1. height and width of the svg tag (defined it here as height="520" and width="100%" (of its parent);
  2. circle tag which takes in cx, cy and r all self explanitory;
  3. same goes for the rect tag which takes in x, y, width, and height;
  4. the group element which applies a tranformation, fill, stroke, etc. to all its children element. These children elements can be any tag (circle, rectangle, or path);
  5. lastly the path where the d attribute is the most important.
    • It can any polygon you desire.
    • It requires a start point M x,y. Then a line to a desired point: L x2,y2.
    • These L points can be grouped as many times as necessary.

Using d3

The above svg elemtns can be replicated with d3.js.

Making a face

Will demostrate how to make more complex shapes with animations. For a demo click the “Start Animation” button.

Making a Bar Chart

Got the data from here: UN Data

Drawing a Scatterplot

Here we will draw a scatterplot

Lineplots

Let us do line plots now

Here are some options you can play with:

Draw a function

Lets draw a function to see how it turns out.

Area Plot

Let us do area plot now

General Update Pattern: Enter, Update, Remove

This section will demonstrate how the enter, update, and remove work with a bowl of fruit example.

If the bowl is empty then add 5 apples. If you eat one remove it from the bowl.

Nested Elements with the General Update Pattern

You can add only one element (like the bowl) by using the: selection.selectAll('rect').data([null]).enter().append('rect')

Making a Map with d3

Lets make a map.

  • Loading and parsing TOPJSON;
  • Rendering geopraphic features;
  • Using different map projections;
  • Rendering projected shpere outline.

Here are some references used here:

Loaded topo json format and d3 requires geo json format. Thus use topojson library for conversion. Got the topojson library from here:

TopoJSON Library

.

Use the topojson.feature(data) function for conversion.

If the path type is sphere then you will get the thick borders around the map.

Code
export const createMapBeg = () => {
  const svg = d3.select("#id");
  const projection = d3.geoMercator();
  const pathGenerator = d3.geoPath().projection(projection);
  d3.json("https://unpkg.com/world-atlas@1.1.4/world/110m.json").then(
    (data) => {
      const countries = topojson.feature(data, data.objects.countries);
      const paths = svg.selectAll("path").data(countries.features);
      paths
        .enter()
        .append("path")
        .attr("d", (d) => pathGenerator(d));
    },
  );
};

Making some tweaks to the map

You will find the types of projections here: Projections,

another link

.

Here is a list of some projections

  • d3.geoOrthographic(); This is used below.
  • d3.geoStereographic();
  • d3.geoEqualEarth();
  • d3.geoGnomonic();

Need to figure out how to resize maps properly, and also how to rotate them.

Tree Visualization

We will create a tree. Uses the d3.hierarchy library. It is there by default.

You can also have vertical trees with the following code:

Code
const treeRoot = d3.hierarchy(data);
const links = treeLayout(treeRoot).links();
const linkPathGenerator = d3
  .linkVertical()
  .x((d) => d.x)
  .y((d) => d.y);

You could use treeLayout = d3.cluster() if the leaft nodes are unlevel to have them appear on the same level.

Color and Size Legend

In this module we will make a legend component.

  • will encode area and sqrt scale
  • Compute ticks from size scale
  • Compute size legend component
  • Lets also make a size scale next to the legend. Size scale is proportional to area and we are going to use circle to represent size. Therefore, r = sqrt(A/pi)

  • Since A is proportional to sqrt of r, we must use the sqrt scale.
  • compute ticks from size scale is also done