Creating visualizations with D3 and TypeScript
Tags: typescript, webdev
Published: 2022-10-18 18:45:55

**Written by [Rosario De Chiara](https://blog.logrocket.com/author/rosariodechiara/)✏️**

This article will chronicle my experiences studying [D3.js](https://d3js.org/), a JavaScript framework that produces high-quality diagrams and graphics fueled by data. 

Although D3 is a JavaScript library, we will use [TypeScript](https://blog.logrocket.com/tag/typescript/) because it handles data and data types more efficiently than plain old JavaScript. 

This tutorial will show you how to create visualizations using D3 and TypeScript. First, we’ll create a simple boilerplate project, add data, and then build a fully interactive example. We will host the code on [CodePen](https://codepen.io) for maximum interactivity as a stylistic decision. 

Each example will run in the browser, saving you the fuss of installing anything onto your computer. Of course, you’ll be able to fork a Pen and work on your code version. 

_Jump ahead:_

*   [Creating and exporting the boilerplate project](#creating-exporting-boilerplate-project)
*   [Adding visualization data to D3](#adding-visualization-data-D3)
*   [Binding the data to graphics](#binding-data-graphics)
*   [Interacting with the visualizations with D3 and TypeScript](#interacting-visualizations-D3-TypeScript)

## Creating and exporting the boilerplate project in D3 <a name="creating-exporting-boilerplate-project">

We will mainly focus on adding dependencies and getting acquainted with the environment with the boilerplate Pen. There will be HTML on the left, CSS in the middle, and TypeScript on the right. This is where most of the action will take place. ![Example of the boilerplate project visualization](https://blog.logrocket.com/wp-content/uploads/2022/10/creating-exporting-boilerplate-project-d3-1.png) 

Next, ensure that the JavaScript pane is set to TypeScript and add D3 as a dependency. You can do this by selecting the **gear icon** on the top right. 

Here’s an interactive example of the code:

See the Pen [Typescript + D3 Boilerplate](https://codepen.io/rosdec/pen/VwxzGVp) by rosdec ([@rosdec](https://codepen.io/rosdec)) on [CodePen](https://codepen.io).

The code is straightforward, so we will only focus on TypeScript because the HTML and CSS are irrelevant.

```typescript
import * as d3 from "https://cdn.skypack.dev/d3@7.6.1";

const svg = d3.select("body")
  .append("svg")
  .attr("width", 500)
  .attr("height", 500);

svg
  .append("text")
  .attr("x", 100)
  .attr("y", 100)
  .text("Hello d3js");

svg
  .append("circle")
  .attr("r", 30)
  .attr("cx", 60)
  .attr("cy", 50);
```

The import addresses the D3 library dependency. In the following block of code, we added the `svg` component to the `body` tag to accommodate our graphics in each code example. 

The last two lines of code add the text and circle to produce the results seen in the Pen. That is everything we need to set up the environment to play with D3.

## Adding data to D3 <a name="adding-visualization-data-D3">

To stay true to the D3 philosophy, we have to add data to our graphics. To do this, we’ll use the code below. This downloads a CSV file and manipulates it to visualize it as a scatter plot.

See the Pen [Typescript + D3 Interactive](https://codepen.io/rosdec/pen/XWqemyY) by rosdec ([@rosdec](https://codepen.io/rosdec)) on [CodePen](https://codepen.io).

```typescript
import * as d3 from "https://cdn.skypack.dev/d3@7.6.1";

// set the dimensions and margins of the graph
const margin = { top: 10, right: 30, bottom: 30, left: 60 },
  width = 460 - margin.left - margin.right,
  height = 400 - margin.top - margin.bottom;

// append the svg object to the body of the page
const svg = d3
  .select("body")
  .append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", `translate(${margin.left}, ${margin.top})`);

// Read the data
d3.csv(
"https://raw.githubusercontent.com/holtzy/D3-graph-gallery/master/DATA/iris.csv"
).then(function (csvdata) {
  // Add X axis
  const x = d3.scaleLinear().domain([3, 9]).range([0, width]);
  const xAxis = svg
	.append("g")
	.attr("transform", `translate(0, ${height})`)
	.call(d3.axisBottom(x));

  // Add Y axis
  const y = d3.scaleLinear().domain([0, 9]).range([height, 0]);
  svg.append("g").call(d3.axisLeft(y));

  // Add dots
  svg.append("g")
     .selectAll("circle")
     .data(csvdata)
     .join("circle")
     .attr("cx", function (d) {
  	   return x(d.Sepal_Length);
	})
	.attr("cy", function (d) {
  	   return y(d.Petal_Length);
	})
	.attr("r", 5);
});
```

After we’ve done the import, we will define the surface to draw our graphics on. We can do this by calculating the area's width and height along with the margins. These values add `svg` to the HTML body and specify a transformation. In this case, it’s a `translate` operation to place `g` under `svg`. 

Our last operation is to map the points in the scatterplot. The data is directly downloaded from a URL as a CSV file. D3 can manipulate CSV data, which comes in handy most of the time. Once the data is available, three operations are performed: adding the x-axis, adding the y-axis, and plotting the data. 

The first two operations are performed consecutively to define the x and y-axes as `scaleLinear`. Then, for each axis, the range is specified by the number of pixels that such axes will occupy. The x-axis will have a domain of `3` to `9`, and the y-axis will be `0` to `9`.

## Binding data to graphics using D3 <a name="binding-data-graphics">

Adding the dots to the scatter plot may appear a little convoluted, but we can do it with a specific sequence of operations. The idea is to bind a graphic component — a circle, a point, and a line — to data. Then, the data will modify some aspects of the graphic component, such as color, thickness, pattern, and position. In the source code above, we:

*   Use `.selectAll` to define the type of element that will join each element of the data
*   Use `.data` to define the array
*   Use `.join` to join the data and the graphics elements. This is where `HTML` or `SVG` are dynamically added and removed

Now, we define how the value of the data influences the graphics element. In the example above, you can see that we `.selectAll` circle elements, we call `.data` to assign the `csvdata` as the data source of the join, and then we `.join` the data to the graphics element. 

Our final and most creative step is defining how the data influence `graphics`. At this point, we only have a circle for each entry in the `csvdata`. To modify the circles, we use `.attr`. The first two will modify the attributes `cx` and `cy` at the center of the circle coordinates, then modify the radius by setting it to `5`.

## Interacting with the visualizations with D3 <a name="interacting-visualizations-D3-TypeScript">

Next, let's add an interaction to explore the real possibilities of D3\. First, let’s look at the final result:

See the Pen [Typescript + D3 Interactive](https://codepen.io/rosdec/pen/XWqemyY) by rosdec ([@rosdec](https://codepen.io/rosdec)) on [CodePen](https://codepen.io).

Together with the scatterplot, we have a button to remove one circle from the data. This is done in D3 without access to external sources. The button is added in HTML but is bound to the code it will execute in the TypeScript source. 

The interaction occurs in `popCircle()` and will remove the last element from the `csvdata` array. This will then join the circles in the scatterplot to data, but with a little addition — the `.exit` operation. This defines what happens when a datum exits the graphics array. 

The semantics of the code is simple: everything after `.exit()` will apply to the graphics elements exiting from the array. Here, we ask D3 to apply a transition on the circle radius specified by `.attr` that will become `0` before removing `graphics` from the representation. 

The final effect is visually satisfying. Once you click the **button**, the scatterplot circles disappear, and the transition alerts the user to where modifications are happening. ![GIF of the final effect of creating visualizations with D3 and TypeScript](https://blog.logrocket.com/wp-content/uploads/2022/10/gif-showing-scatterplot-visualizations-d3-typescript.gif)

## Conclusion

In this tutorial, we learned how to set up a stripped-down project based on TypeScript and D3\. We also saw how to go from a basic representation to an advanced and interactive data-driven one. Although the example is simple, I hope it clearly shows where to intervene to produce data-driven graphical representations.

---
## [LogRocket](https://lp.logrocket.com/blg/signup): Full visibility into your web and mobile apps

[![LogRocket signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://lp.logrocket.com/blg/signup)

[LogRocket](https://lp.logrocket.com/blg/signup) is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.

[Try it for free](https://lp.logrocket.com/blg/signup).