Friday, 1 April, 2022 UTC


Summary

Introduction

Data helps us tell compelling stories, data visualization is the graphical representation of information and data using graphic elements such as charts, graphs, and so on, there are a few libraries out there that can help us produce beautiful outcomes with relatively little work and Chart.js is one of them.
In this guide, we will look at how to construct charts in JavaScript using Chart.js, as well as the numerous customization and styles that Chart.js provides to enable us make beautiful charts.

Getting Started

Chart.js is a popular community-maintained open-source data visualization framework. It enables us to generate responsive bar charts, pie charts, line plots, donut charts, scatter plots, etc. All we have to do is simply indicate where on your page you want a graph to be displayed, what sort of graph you want to plot, and then supply Chart.js with data, labels, and other settings. The library does all the heavy lifting after that!

Installation

To get started with Chart.js, we must first install it as it's a third-party library. Chart.js may be installed via npm, GitHub releases, or the Chart.js CDN, which is the quickest and easiest method.
For this guide, we will make use of the Chart.js CDN. You may do so by getting the most recent CDN link and adding it in your project.
Note: Please use the URL with Chart.min.js at the end, as this is the minified version.
As of the time of writing, the most recent version is 3.7.1. All you have to do is add the following to the head element of your HTML file:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
Once this is completed successfully, we can use the library.

Creating Charts With Chart.JS

For this guide, we will create several sorts of charts, highlighting the most popular JavaScript frameworks based on the amount of GitHub Stars they currently have. Here is the information we will be using:
JavaScript Framework GitHub Stars
React 185,134
Vue 195,514
Angular 80,460
Svelte 57,022
Ember.js 22,165
Backbone.js 27,862

Create a Canvas to Render the Charts

The first step would be to provide a location in our HTML for the chart to be rendered. Chart.js relies on the availability of the HTML5 Canvas tag (used to draw lines, circles, and so on) to generate and render the charts. More information regarding the Canvas API may be found here.
All we have to do is construct the canvas tag within the body tag and provide an ID that we will need to call fetch the element and reference our specified graph element in JavaScript:
<canvas id="myChart" width="1000" height="600"></canvas>
Note: We may call the ID whatever we wish, however it is advised that we pick a descriptive name that represents the type of charts we want to generate. If we're adding many graphs to a page, it is important we make ensure that each ID is distinct (we could for example give our graphs more specific names, like studentsChart or productChart, e.t.c.).
Here is what our HTML file should look like now:
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.min.js"></script>
		<title>Programming Lang. Chart</title>
	</head>
	<body>
		<canvas id="myChart" width="1000" height="600"></canvas>

		<script src="./App.js"></script>
	</body>
</html>

Prepare and Organize Our Data

We have to save the previously supplied information (frameworks and stars). The most convenient format for us is to save it in an object, where the keys represent frameworks and values represent stars. In our App.js, let's define our data:
const data = {
    'React': 185134,
    'Vue': 195514,
    'Angular': 80460,
    'Svelte': 57022,
    'Ember.js': 22165,
    'Backbone.js': 27862
};

Creating a Bar Chart

Let's get started with the core logic; we'll see how to make a bar chart and, later, how to make additional charts by easily altering our parameters. The great thing about Chart.js is that once you create a Chart object - to alter it, you just change the type attribute and leave everything else as it was!
The first step is to take the canvas element from HTML with the ID myChart and assign it to a context variable - typically named ctx:
const ctx = document.getElementById('myChart').getContext('2d');
Note: We may name the variable whatever we like; ctx is simply a pattern that most developers prefer, and it's what we'll be using. .getContext('2d') is an optional method that allows us to access the canvas tag's 2D drawing capabilities.
To create a Chart object, we call the new Chart() constructor, which accepts two arguments:
  • ctx: the context object, referencing the canvas element we're plotting on.
  • Configuration object: enables us to set the chart type, data, and chart parameters.
const myChart = new Chart(ctx, {});
We will be working with the configuration object to help us create our bar chart. As we said earlier, the configuration object lets us specify the:
  • Chart type: The sort of chart we wish to generate. In this scenario, we're making a bar chart. We might provide type: 'pie' or type: 'line' if we wanted a pie or line chart.
  • Chart data: Labels and values that will be utilized to create the charts.
  • Chart options: Configuration choices for customizing the charts, such as adjusting the location of the legend, enabling/disabling responsiveness, control style, and so on.
Let's set up a skeleton configuration object:
{
  type: 'bar',
  data: {},
  options: {} // this is optional
}
This object can then be passed into the chart instantiation. Let's add the chart data alongside the type:
const myChart = new Chart(ctx, {
	type: 'bar',
	data: {
		labels: Object.keys(data),
		datasets: [
			{
				label: 'Number of GitHub Stars',
				data: Object.values(data),
			},
		],
	},
});
Since we're dealing with an object - we can extract its keys and values via the Object.keys() and Object.values() methods. Alternatively, you can procure the labels and values in separate arrays as well!
Understanding the Data Property
Labels and datasets are the two attributes of the data property object. The labels represent an array of components that will be shown on the X-axis:
While, the datasets takes an array of objects which has two basic properties:
  • label: A string which is usually displayed on top of the chart or when hovering the bars, as seen below:
  • data: An array of values, which is shown on the Y-axis and reflects the GitHub stars numbers in our example:
Note: You can have many datasets, each with their own unique "suptitle" (label) and data. If you plot several datasets, it helps to have different colors to signify the difference. We'll cover this use case in a moment.
In summary - to plot a bar chart, we prepare the canvas/context and initialize a Chart() with our data and labels:
const data = {
    'React': 185134,
    'Vue': 195514,
    'Angular': 80460,
    'Svelte': 57022,
    'Ember.js': 22165,
    'Backbone.js': 27862
};

const ctx = document.getElementById('myChart').getContext('2d');

const myChart = new Chart(ctx, {
	type: 'bar',
	data: {
		labels: frameworks,
		datasets: [
			{
				label: 'Number of GitHub Stars',
				data: stars,
			},
		],
	},
});
When you refresh your browser - the page should contain something along the lines of:
Horizontal Bar Chart
To flip the bar chart to a horizontal one - you set the indexAxis property yo y in the options object:
const myChart = new Chart(ctx, {
  type: 'bar',
  data: {
    ...
  },
  options: {
    indexAxis: 'y',
  }
});
Note: In previous versions of Chart.js, you'd replace type:bar with type:horizontalBar, though, this has been deprecated since.
Styling the Bar Chart
At this point, we have successfully created a bar chart! Though, data visualization is about story telling - not just data. We usually want to make the chart more visually appealing! Additionally, not styling the chart can not only make it dull - but unreadable. For instance, if a pie chart has all wedges of the same color, you wouldn't really be able to differentiate between different classes, unless you add borders to each wedge.
We can alter some of these options via: backgroundColor, borderColor and borderWidth .
backgroundColor - Takes an array of Hexadecimal or RGBA color values (strings) to be used to color the chart's bars. This may also be done with a single color because it will be applied to all the bars:
backgroundColor: 'red' // Setting all bars to red

// Or

backgroundColor: [
  'rgba(255, 99, 132, 0.2)',  // Bar 1
  'rgba(54, 162, 235, 0.2)',  // Bar 2
  'rgba(255, 206, 86, 0.2)',  // Bar 3
  'rgba(75, 192, 192, 0.2)',  // Bar 4
  'rgba(153, 102, 255, 0.2)', // Bar 5
  'rgba(255, 159, 64, 0.2)'   // Bar 6
],
borderWidth - It takes an Integer or a float value, and it specifies how wide a border should be:
borderWidth: 2
borderColor - The same as the backgroundColor property, it accepts an array of color value strings. It will colorize the bar's borders:
borderColor: 'green' // Setting all borders to green

// Or

borderColor: [
  'rgba(255, 99, 132, 1)',    // Bar 1
  'rgba(54, 162, 235, 1)',    // Bar 2
  'rgba(255, 206, 86, 1)',    // Bar 3
  'rgba(75, 192, 192, 1)',    // Bar 4
  'rgba(153, 102, 255, 1)',   // Bar 5
  'rgba(255, 159, 64, 1)'     // Bar 6
],
Note: All these properties and their values are part of the data object, right after datasets.
Combining these together, you can make a nicely stylized bar chart as:
const myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: Object.keys(data),
        datasets: [{
            label: 'Number of GitHub Stars',
            data: Object.values(data),
        }, ],
    },
    options: {
        backgroundColor: [
            'rgba(255, 99, 132, 0.2)',  // Bar 1
            'rgba(54, 162, 235, 0.2)',  // Bar 2
            'rgba(255, 206, 86, 0.2)',  // Bar 3
            'rgba(75, 192, 192, 0.2)',  // Bar 4
            'rgba(153, 102, 255, 0.2)', // Bar 5
            'rgba(255, 159, 64, 0.2)'   // Bar 6
        ],
        borderWidth: 2,
        borderColor: 'black'
    }
});
How to Control Charts Width and Height
So far, if you've been viewing the chart in your browser, you've probably noticed that the browser is displaying the chart full screen and isn't respecting the width and height we previously set on the canvas element:
<canvas id="myChart" width="800" height="400"></canvas>
To resolve this, we must add configurations to our bar chart instance by passing some options in the options object. These are the options:
  • maintainAspectRation: this is set to false to respect the height we previously added to the canvas. This means that my chart would be 400 pixels tall.
  • responsive: This is set to false to gain complete control over the canvas's width.
const myChart = new Chart(ctx, {
  type: 'bar',
  data: {
    // Data...
  },
  options: {
    // ... Other options
    maintainAspectRatio: false,
    responsive: false
  }
});
It would be helpful to explain how this could be accomplished using CSS, which is another method for controlling the width and height of your chart. This option necessitates additional markup, but is more flexible because our chart will still be responsive!
Note: We must remove the options object, as well as the canvas tag's height and width.
Let’s now wrap the canvas tag in a div which we would use to style the chart:
<div class="container">
	<canvas id="myChart"></canvas>
</div>
In our CSS, all we need to do is apply a max-width and set its margin to 0 auto, so it resizes and appears in the middle:
.container {
	max-width: 800px;
	margin: 0 auto;
}
When you now reload your browser, you will notice it's responsive, and it also respects the max-width set!

Plotting Line Charts, Donut Charts, Polar Areas and Radar Plots with Chart.js

Creating charts is very simple, all we have to do is to change the type from type: "bar" to the specific type you want. This could be pie, horizontalBar, line, doughnut, radar, polarArea, scatter etc.

More Stylings

Let's now take a look at a few more styling options that can be performed with Chart.js easily.

Global Stylings/Configurations

Chart.js allows us to declare some global configurations, defined in Chart.defaults.
Let's use this to adjust the font-family, font-size, font-style and font-weight of our chat globally, so it applies to every text on the chart. These options can be found in Chart.defaults.font.
Chart.defaults.font.size = 10;
Chart.defaults.font.weight = 'bold';
Chart.defaults.font.family = 'Lato';
Chart.defaults.font.style = 'italic';
Note: The global font settings only apply when more specific options are not included in the config of an individual chart.
For example, in this chart the text will have a font size of 16px except for the title text which has a specific size assigned to it:
Chart.defaults.font.size = 16;
let chart = new Chart(ctx, {
	type: 'line',
	data: data,
	options: {
		plugins: {
			title: {
				text: 'Popular JavaScript Frameworks',
				font: {
					size: 25,
				},
			},
		},
	},
});
Note: We can also add global color for all texts in our chat by using Chart.defaults.color.

Setting Titles

A plugin within the options object can be added to specify the title:
options: {
  ...
  plugins: {
    title: {
      display: true,
      text: 'Popular JavaScript Frameworks',
      font: {
        size: 25
      }
    },
  }
}
Note: This accepts more styles like position, padding, font, e.t.c. More details are in the Chart.js official documentation.

Adding Legends

Legends are a great way to help users connect classes and their labels to their colors. Legends can also be declared/styled globally using Chart.defaults.plugins.legend in case you have multiple charts and don't want to repeat the same code:
plugins: {
  ...
  legend: {
    display: true,
    position: 'right'
  }
}
Note: For other charts asides the ones mentioned earlier, it's best to set display to false.

Conclusion

So far in this tutorial, we have been able to learn how to make use of Chart.js to create all forms of graph and also see how we could apply styling which can become very tricky if you don’t understand how it works properly.