D3 Tutorial

In this post, I outline-solid the ways in which d3 library works with the <svg> elements.

D3 Tutorial

Working with Javascript

We have the following data of cars

List of Cars

[
    {
        "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.

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

Output:

/*
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.

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

Result of applying the filter method used here

[
    {
        "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.

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:

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