Build Interactive and Responsive Charts with Chart.js

Subscribe to my newsletter and never miss my upcoming articles

Listen to this article

Data visualization is the act of presenting data into visual forms such as graphs or charts. It is used to summarize data easily and communicates its relationships with other data if needed. It helps to organize data and allows new insights or patterns to be discovered.

As developers, it is important to learn some data visualization tools. In my How I Built an Image Classification Pokedex article, the app fetches data from the PokeAPI and organizes them into the page below:

image.png

In this article, let's look at Chart.js, the library I used to make these charts, which can be used to organize any form of data into readable visual data.

image.png

Getting Started

In this tutorial, I'll use PokeAPI data as examples when I explain how to make these charts. Feel free to use any data you want to organize them using Chart.js.

1. Bar Chart

First, import the library into the HTML page:

<script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>

Then, add the canvas HTML element with a bar-chart id attribute. This will be where the bar chart renders.

<canvas id="bar-chart"></canvas>

In a script.js, create a simple function to fetch data from a URL like the snippet below. I won't be going into much detail about how to fetch in this tutorial as this is primarily for Chart.js.

function fetchPokemon(name) {
  return new Promise((resolve, reject) => {
    fetch(`https://pokeapi.co/api/v2/pokemon/${name}`).then((res) => {
      if (res.status === 200) {
        resolve(res.json());
      } else if (res.status === 404) {
        return reject({
          status: 404,
          message: "No pokemon named" + name + " is found.",
        });
      } else {
        reject({
          status: res.status,
          message: "Something went wrong...",
        });
      }
    });
  });
}

Next, create a loadBarChart function which will accept a data parameter to organize our data in the way which we want it to. Here's how we can implement it.

  1. Get the reference for the canvas element by its id attribute.
  2. Get the data we want to display as bars.
  3. Instantiate new Chart, set it as type: "bar" and set the data.
function loadBarChart(data) {
  //1.
  let barChart = document.getElementById("bar-chart");
  //2.
  const { base_experience, base_happiness, capture_rate } = data;
  //3.
  barChart = new Chart(barChart, {
    type: "bar",
    data: {
      datasets: [
        {
          data: [base_experience],
          label: "Base Experience",
          backgroundColor: "rgba(197,48,48,0.5)", //red
          borderColor: "rgba(255, 99, 132, 1)",
          borderWidth: 1,
        },
        {
          data: [base_happiness],
          label: "Base Happiness",
          backgroundColor: "rgba(75, 192, 192, 0.5)", //green
          borderColor: "rgba(75, 192, 192, 1)",
          borderWidth: 1,
        },
        {
          data: [capture_rate],
          label: "Capture Rate",
          backgroundColor: "rgba(255, 159, 64, 0.5)", //yellow
          borderColor: "rgba(255, 159, 64, 1)",
          borderWidth: 1,
        },
      ],
    }
}

As you can see, making a bar chart is as easy as just setting the type and data. The datasets in data is an array of the individual data objects which will render as a bar as seen in the image below.

image.png

In this example, datasets contains the base_experience, base_happiness and capture_rate data. You can also customize each data object in terms of their label, backgroundColor, borderColor or even borderWidth properties. For example, I customized their labels and colour them in red, green and yellow.

Of course, there are more customization options and styling to choose from. Feel free to read the bar chart documentation for more details. Let's now move on to Pie Charts.

2. Pie Chart

A pie chart is pretty straightforward. It shows a relationship between 2 or more data in terms of percentage. A full pie means 100%.

For my example, I will display a gender ratio as a pie chart. First, create the canvas element for the pie chart to render in.

<canvas id="pie-chart"></canvas>

After fetching from PokeAPI, get the femalePercent data and pass it into the loadPieChart function. Here's how loadPieChart works.

  1. Get the reference for the canvas element by its id attribute.
  2. Instantiate new Chart, set it as type: "pie" and set the data.
function loadPieChart(femalePercent) {
  //1.
  let pieChart = document.getElementById("pie-chart");
  //2.
  pieChart = new Chart(pieChart, {
    type: "pie",
    data: {
      datasets: [
        //only 1 data obj in datasets
        {
          data: [femalePercent, 100 - femalePercent], // female, male
          backgroundColor: [
            "rgba(255,137,180, 0.5)", //pink for female
            "rgba(44, 130, 201, 0.5)", //blue for male
          ],
          borderColor: ["rgba(255,137,180,1 )", "rgba(44, 130, 201,1)"],
          borderWidth: 1, //they share the same value so no need array
        },
      ],
      //add custom labels, female first then male
      labels: ["Female", "Male"],
    },
  });
}

For pie chart, there should only be one data object in datasets because femalePercent and 100-femalePercent(male) combines into 1 whole data. They are not individual data with no relationship to each other.

So now the data in datasets is an array of the data values for the pie chart. In this case, it is the femalePercent and the malePercent which is 100-femalePercent.

Then, we add custom styling such as labels, backgroundColor, borderColor and borderWidth. They are also arrays which represents the female and male percent respectively. Keep in mind that these styling should have the female properties first in their array because that's how it was ordered in the data object.

And we'll get a simple pie chart for our gender ratio data!

image.png

3. Radar Chart

A radar chart is helpful to show a big-picture view on how individual data differs from each other. For my app, I used it to show the stats of a Pokémon and to easily determine its best and the worst stat.

image.png

To make a radar chart is simple. First, create the canvas element for the radar chart to render in.

<canvas id="radar-chart"></canvas>

Then, create a loadRadarChart function as follows:

  1. Get the reference for the canvas element by its id attribute.
  2. Instantiate new Chart, set it as type: "radar" and set the labels and data properties.
function loadRadarChart(data) {
  //1.
  let statsChart = document.getElementById("radar-chart");
  //2.
  statsChart = new Chart(statsChart, {
    type: "radar",
    data: {
      //Will show up on each radar points in clockwise order
      labels: ["HP", "Attack", "Defense", "Sp. Atk", "Sp. Def", "Speed"],
      datasets: [
        {
          //one data obj per set, order same as labels
          data: [
            data[0]["base_stat"], //HP
            data[1]["base_stat"], //Atk
            data[2]["base_stat"], //Def
            data[3]["base_stat"], //SpA
            data[4]["base_stat"], //SpD
            data[5]["base_stat"], //Speed
          ],
          backgroundColor: "rgba(197,48,48,0.5)", // red
        },
        /*Add another set if needed like so
        {
           data: [ ]
        },
        */
      ],
    },
  }
}

Just like a pie chart, there should be one data object in the datasets array, unless you want to add another separate dataset like the image below.

image.png

The data object should contain an array of the data values. They will be arranged in clockwise so in this example, HP would start at 12 o'clock and Atk would be on its right and so on.

Remember to add the labels array in the same order as data in order to label each point on the radar chart correctly. Then, you may customize it as usual. Here, I customize its backgroundColor to red.

4. Line Chart

Last but not least, we will build a line chart. This type of chart is to plot points on a line to see trends and to compare if there are multiple lines.

In my app example, I used it to plot a growth chart, using level as the x-axis and experience gained as the y-axis.

image.png

In order to plot a line graph, you need an array of x and y values like the snippet below. Note that the x-axis property (i.e. level) is listed above the y-axis property (i.e. experience).

data = [
   {
      level:10, //x-axis
      experience:560 //y-axis
   },
   {
      level:20, //x-axis
      experience:5460 //y-axis
   },
   //And so on...
]

Once you have a dataset to plot, create the canvas element where the line graph will render on.

<canvas id="line-chart"></canvas>

As usual, create a loadLineChart function as follows:

  1. Get the reference for the canvas element by its id attribute.
  2. Instantiate new Chart, set it as type: "line" and set the labels and data properties.
function loadLineChart(data) {
  //1.
  let growthChart = document.getElementById("growth-chart");
  //2.
  growthChart = new Chart(growthChart, {
    type: "line",
    data: {
      labels: data.map((d) => d.level), //x-axis data
      datasets: [
        {
          label: "Growth Rate",
          data: data.map((d) => d.experience), //y-axis data
          backgroundColor: "rgba(153, 102, 255, 0.5)", //purple
          borderColor: "rgba(153, 102, 255, 1)",
          borderWidth: 1,
        },
      ],
    }
  }
}

As seen in the code above, the labels property will plot the x-axis values (i.e. level) while the data in datasets takes care of the y-axis values (i.e. experience).

Result

And with that, you can easily make interactive charts using Chart.js! As you can see in the GIF below, hovering over each data point will display a tooltip about the data so users can take a closer look at the graphs.

ezgif.com-gif-maker.gif

Thanks for reading! I hope this article serves a simple introduction to how you can build various types of charts using Chart.js. If it is helpful, please do like and share this article around. Of course, there are more options and customization features in Chart.js. Feel free to browse its documentation (under Resources) to learn more. Till next time, cheers!


Resources

Comments (3)

JC Lee's photo

Great introduction to chart js 😍!!!

Victoria Lo's photo

Thanks! I'm glad it helped :)

JC Lee's photo

Victoria Lo I haven't assimilated it all today 😁. But will come back to it when I need charts 👌.