Shajia Abidi Full-Stack Developer with experience of working with IoT, Media, and Travel companies. Have developed data-driven interactive web apps using HTML5, CSS3, JavaScript, React, Redux, Python and other JS frameworks and libraries.

Data visualization with Vue and D3

6 min read 1714

Vue logo.

For the last few months, we’ve seen a lot of visualizations answering questions about COVID-19. Is the virus spreading? How many deaths have been caused by it? What is the projection of these deaths? Which states have the highest number of positive cases? Who is being most affected by it?

These visuals help us understand the numbers better. Instead of performing complex calculations, these visuals help the human brain perceive the information better and faster. And they are much more fun to look at and play with than a spreadsheet full of numbers.

In this article, we’re going to create a line chart representing the popularity of the word COVID in Google Search across various regions and languages.

For this tutorial, we will be utilizing the following tools:

  • D3: A JavaScript library for producing dynamic, interactive data visualizations in web browsers
  • Vue: A progressive JavaScript framework for building user interfaces

Vue

Vue.js is one of the many JavaScript frontend frameworks for building user interfaces. Even though Vue, created by Evan You, has been around for just a few years, it has about 168K stars on GitHub and is one of the leading JS frameworks today.

I’ve worked with different JS frameworks, including Angular, React, and Vue. In my opinion, Vue has been the easiest to work with.

This article will assume you’ve working knowledge of Vue, but if you need a refresher, the official documentation is very well maintained and easy to understand.

D3

There are numerous JS libraries used today for data visualization. Some libraries are used to create 3D visuals like three.js and Babylon.js, and others that are multipurpose like HighCharts, Recharts, and D3.

With over 92K stars on GitHub, D3, created by Michael Bostock, without a doubt, is the leading JavaScript library for data visualization.

D3, which stands for Data-Driven Documents, manipulates the DOM based on the data.

We made a custom demo for .
No really. Click here to check it out.

According to the official documentation:

D3 helps you bring data to life using HTML, SVG, and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.

There are hundreds of examples to look at and learn from. From a simple bar chart to a more complex chord diagram visualizing debts between countries, you can make anything come alive with D3.

Apart from being a powerful tool for creating visuals, D3 has a huge open-source community. If you have an idea for a graphic, there is a chance somebody somewhere has created something similar and has written about it. Or if you’re stuck at creating a tooltip or an animation, there’s a good chance StackOverflow will have an answer for you.

The bottom line is that you’re never alone.

This article is going to assume that you have the working knowledge of D3. I will also assume you have Vue CLI installed, and if not, you can get the installation directions from here.

Once we are in the directory we want to work in, let’s create a new Vue project, cd into it, and open it in our editor. While we are it, let’s also install D3:

$ vue create VUE-D3 && cd VUE-D3 && code .
$ yarn add d3

Now that we have everything installed, let’s start coding.

  • In App.vue, remove all the content in the <template> tag, styles and the imports
  • Create a new file inside our component folder, name it Charts.vue, and import d3 in it
  • Make sure wee import the newly created file in our App.js and add it in our <template>
  • To serve our app, we will run yarn serve

Line Chart

D3 is a vast library with tons of modules. To utilize them effectively, it’s crucial to understand the basics. For this tutorial, we will be creating a line chart. Let’s jump into it.

Our first step should always be to explore the data. There are some questions you can ask, like where are we getting the data from? What format is it in? Do we have dates? If yes, how should we handle dates?

Exploring data is extremely helpful and saves us a lot of time.

We are getting our data from Google Trends in the form of a CSV file. We convert this into a JSON using an npm package called csvtojson.

Once we have installed the package, we can run the following command in our terminal, and we will have a JSON file:

csvtojson path-to-the-file/name-of-file > path-where-to-save-the-file/name-of-the-file

Next, store the json file in our assets folder and import it in our Charts.vue file. In our mounted function, let’s run this command:

console.table(dataset[0])

A screenshot of the console table.
Console.table is efficient because it returns data as a table, making it easier to read. As we can see, we have two fields in our object.

Day: a string representation of a date and a number representing the popularity of the search word. Read more about how Google calculates the popularity here.

The data tells us two things:

  • We need a parser to parse the date string into a date
  • We need to convert COVID to a number

Now we are aware of our data types and know how to proceed. In our working file, we will add a div and give it an id chart. We will use this id to select this div using D3:

<template>
 <div id="chart" />
</template>

In our data object, let us define some dimensions:

data() {
   return {
     width: 750,
     height: 400,
     margin: {
       top: 50,
       right: 50,
       left: 50,
       bottom: 50,
     },
   };
 },

Whenever the component mounts, we want D3 to access the div and append an SVG.

We select elements via D3 selection. D3’s select takes in a value that uniquely defines the element we want to select. In this case, we will use the id chart. We can also pass in the tag name or a class.

We will also append a <g>, i.e. group element. As the name suggests, this element groups all the elements together. It’s helpful in particular when we want to transform child elements.

In our mounted function, we will create a helper function called init:

methods: {
   init() {
     //We are accessing the div with the id chart using d3's select method and appending svg
     const svg = d3
       .select("#chart")
       .append("svg")
         .attr("width", this.width)
         .attr("height", this.height)
       .append("g")
       .style(
         "transform",
         `translate(${this.margin.left}px, ${this.margin.top}px)`
       );

If we run the app and inspect the element, we should see a <g> element enclosed within an svg.

Before we create our line, let’s create accessor functions. In her book, Amelia Wattenberger defines them as functions that convert a single data point into the metric value.

Instead of using d => d. Day, every time we need to access the Day value, we can create a function that will take the data point as an argument and return the Day value. This ensures our code stays DRY and clean.

const yAccessor = (d) => parseInt(d.COVID); //Converting string into a number
const xAccessor = (d) => d.Day;

If you remember from earlier, we have to convert the string into a date object. We will use a d3 date module, which will parse our string into a date object. Our xAccessor will then be updated to become:

const dateParser = d3.timeParse("%Y-%m-%d");
const xAccessor = (d) => dateParser(d.Day);

Let’s create our scales next. They are used to transform data values into visual variables.

D3 scales need two pieces of information: domain and range. Simply put, the domain is the input we give, and the range is the output we want.

In the beginning, it was hard for me to remember which is which (maybe you’re smart, and you don’t). Whenever I am confused, I remember d is for data, and d is for the domain.

For yScale, we have a linear value, i.e., numbers increasing linearly, and so we will use scaleLinear(). For xScale, we have months, so we will use scaleTime().

const yScale = d3
       .scaleLinear()
       .domain([40, 100])
       .range([boundedHeight, 0]);

const xScale = d3
       .scaleTime()
       .domain(d3.extent(dataset, xAccessor))
       .range([0, boundedWidth]);

D3 provides us with the shape module to work with more complex shapes such as symbols, lines, arcs, etc. Since we are creating a line chart, we will be using d3.line(). While creating a line generator, make sure to add the scales.

Once we have the line generator, we can use it to compute the d attribute of our SVG path element.

const line = d3
       .line()
       .x((d) => xScale(xAccessor(d)))
       .y((d) => yScale(yAccessor(d)))

     svg
       .append("path")
       .attr("d", line(dataset))
       .attr("fill", "none")
       .attr("stroke", "rgb(34 150 243)")
       .attr("stroke-width", 3);

Lastly, let’s create our axis. We will use axisLeft() to generate a vertical Axis and axisBottom() to create a horizontal axis. In this example, we have defined ticks. D3 will automatically mark some reference marks, but if you choose to customize the ticks, you could use ticks().

const yAxisGenerator = d3
       .axisLeft()
       .scale(yScale)
       .ticks(5)
       .tickValues(d3.range(25, 100 + 25, 25));

     svg.append("g").call(yAxisGenerator);

     const xAxisGenerator = d3.axisBottom().scale(xScale).ticks(5)

     svg
       .append("g")
       .call(xAxisGenerator)
       .style("transform", `translateY(${boundedHeight}px)`);

If we run our app, we will now see a line chart representing the popularity of COVID.

And this is it. If we run our app, and if everything went fine, we should be able to see a line chart representing the popularity of COVID.

By taking a closer look at the chart, we can see there were fewer searches for COVID on July 4, July 5, July 12 and July 19, as compared to searches on July 14 where it was the highest.

We don’t have to memorize the table to know when the searches were high or low. By just looking at a good data visualization, we can have that information.

Conclusion

D3 is a vast library, and even though we covered a lot, this was just the basics. We can create a lot of different kinds of charts using D3. If you want to learn more, look at some inspirations on Observable or bl.ocks. Try adding some interactions to this chart.

Experience your Vue apps exactly how a user does

Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.

Modernize how you debug your Vue apps - .

Shajia Abidi Full-Stack Developer with experience of working with IoT, Media, and Travel companies. Have developed data-driven interactive web apps using HTML5, CSS3, JavaScript, React, Redux, Python and other JS frameworks and libraries.

Leave a Reply