Often Creating charts with pure css is not the best way. it's better to use canvas or external libraries. Show Table of Contents
Here is a pie chart without using external libraries, using html5 canvas (fiddle) :
fiddle (code is written based on this solution) But it's better to use libraries for drawing charts. in Here is a
clean donut chart using
See it on codepen In this tutorial, I will show you how to use JavaScript and the canvas to display numerical information in the form of pie charts and doughnut charts. What Is a Pie Chart?A chart is a statistical tool used to graphically represent numerical data. A pie chart displays that numerical data as a circle divided into slices. The size of each slice is proportional to the numeric value that it stands for. What Is a Doughnut Chart?To put it simply, a doughnut chart is a variation on a pie chart. The difference is that the slices are cut towards the center of the pie such that only the rim is visible. In this way, the chart looks like a doughnut, hence the name. Start Drawing With the CanvasBefore drawing the pie chart, we will take a look at drawing its parts. We will see how we can use the canvas component and JavaScript to draw:
To start drawing using the HTML5 canvas, we'll need to create a few things:
We'll keep things very simple and add the following code inside index.html: <html> <body> <canvas id="myCanvas"></canvas> <script type="text/javascript" src="script.js"></script> </body> </html> We have the Inside script.js, the JS code will first get a reference to the canvas and then set its width and height. To draw on the canvas, we only need a reference to its 2D context, which contains all the drawing methods. var myCanvas = document.getElementById("myCanvas"); myCanvas.width = 300; myCanvas.height = 300; var ctx = myCanvas.getContext("2d"); Adding a Few Helper FunctionsNow that we have the canvas set up and also a reference to the drawing canvas, let's define a few JavaScript functions that we will be able to reuse when drawing the pie chart. We will add the functions in our script.js file. function drawLine(ctx, startX, startY, endX, endY, color){ ctx.save(); ctx.strokeStyle = color; ctx.beginPath(); ctx.moveTo(startX,startY); ctx.lineTo(endX,endY); ctx.stroke(); ctx.restore(); } The
The first thing we do inside
the function is save the current context. After that, we start drawing the line by calling Let's now see how we can draw a part of a circle, also called an arc. function drawArc(ctx, centerX, centerY, radius, startAngle, endAngle, color){ ctx.save(); ctx.strokeStyle = color; ctx.beginPath(); ctx.arc(centerX, centerY, radius, startAngle, endAngle); ctx.stroke(); ctx.restore(); } The
We've seen how to draw a line and how to draw an arc, so now let's see how to draw a colored shape. Since our goal is to draw a pie chart that is made up of slices, let's create a function that draws a pie slice. function drawPieSlice(ctx,centerX, centerY, radius, startAngle, endAngle, fillColor, strokeColor) { ctx.save(); ctx.fillStyle = fillColor; ctx.strokeStyle = strokeColor; ctx.beginPath(); ctx.moveTo(centerX, centerY); ctx.arc(centerX, centerY, radius, startAngle, endAngle, strokeColor); ctx.closePath(); ctx.fill(); ctx.restore(); } The
Here is an example for calling three functions: drawLine(ctx, 200, 200, 300, 300, "#000"); drawArc(ctx, 250, 250, 150, 0, Math.PI/3, "#000"); drawPieSlice(ctx, 250, 250, 150, Math.PI/2, Math.PI/2 + Math.PI/3, "#F00", "#000"); It will produce this result: Now we have all the tools necessary to draw a pie chart, so let's see how we use them together. Drawing the Pie ChartConceptually, any chart has two main parts:
The Pie Chart Data ModelThe most common way to structure the data model for pie charts is a series of categories and corresponding values, where each category and value is associated with a slice of the pie. As an example, the data model of a pie chart displaying the number of vinyls I have grouped by genre would look something like:
This data can be passed to our pie chart drawing class in the form of an object. We will be passing it to our { "Classical Music": 16, "Alternative Rock": 12, "Pop": 18, "Jazz": 32, } The Pie Chart Graphical RepresentationThe pie chart uses a circle to display the information in the data model by dividing it into slices. Each slice corresponds to a category from the data model, and the size of the slice is proportional to the category value. My small collection of 88 vinyls has four categories. Each category will get a slice of the pie chart proportional to the number of vinyls in that category. But how do we
measure the size of a slice? That's easy—we do that by the angle at the tip of the slice. All we have to know is that the full circle corresponds to an angle of To determine the angle for each category slice, we use the formula:
According to this formula, the 16 classical music vinyls will get a slice angle of approximately 0.36 * PI or 64.8 deg. Let's
get to drawing. For this, we will use a JavaScript class which we will name
The var Piechart = function(options){ constructor(options) { this.options = options; this.canvas = options.canvas; this.ctx = this.canvas.getContext("2d"); this.colors = options.colors; this.titleOptions = options.titleOptions; this.totalValue = [...Object.values(this.options.data)].reduce((a, b) => a + b, 0); this.radius = Math.min(this.canvas.width / 2, this.canvas.height / 2) - options.padding; } drawSlices() { var colorIndex = 0; var startAngle = -Math.PI / 2; for (var categ in this.options.data) { var val = this.options.data[categ]; var sliceAngle = (2 * Math.PI * val) / this.totalValue; drawPieSlice( this.ctx, this.canvas.width / 2, this.canvas.height / 2, this.radius, startAngle, startAngle + sliceAngle, this.colors[colorIndex % this.colors.length] ); startAngle += sliceAngle; colorIndex++; } } } The class starts by storing the passed We convert our object values into an array inside the constructor and then use the reduce() method to get the total of all data points. This value is later used to calculate the angle of different slices. We also calculate the radius of our pie chart within the constructor method by taking the minimum value between half of the canvas width and half of the canvas height and then subtracting the padding. Subtracting the padding to calculate the radius helps introduce some space between different chart elements. The To use the class, we have to create an instance and then call the var myPiechart = new Piechart( { canvas: myCanvas, data: { "Classical Music": 16, "Alternative Rock": 12, "Pop": 18, "Jazz": 32 }, colors: ["#80DEEA", "#FFE082", "#FFAB91", "#CE93D8"] } ); myPiechart.drawSlices(); And the result looks like this: Drawing the Doughnut ChartWe've seen how to draw the pie chart. We also know that a doughnut chart differs only by having a hole in the middle of the chart. How do we draw the hole? We can draw a white circle over the pie chart. Let's modify the
drawSlices() { var colorIndex = 0; var startAngle = -Math.PI / 2; for (var categ in this.options.data) { var val = this.options.data[categ]; var sliceAngle = (2 * Math.PI * val) / this.totalValue; drawPieSlice( this.ctx, this.canvas.width / 2, this.canvas.height / 2, this.radius, startAngle, startAngle + sliceAngle, this.colors[colorIndex % this.colors.length] ); startAngle += sliceAngle; colorIndex++; } if (this.options.doughnutHoleSize) { drawPieSlice( this.ctx, this.canvas.width / 2, this.canvas.height / 2, this.options.doughnutHoleSize * this.radius, 0, 2 * Math.PI, "#FFF", "#FFF" ); drawArc( this.ctx, this.canvas.width / 2, this.canvas.height / 2, this.options.doughnutHoleSize * this.radius, 0, 2 * Math.PI, "#000" ); } } The added code looks in the The radius of the circle is determined by multiplying the pie chart radius and the value of To draw a doughnut chart with a hole half the size of the chart, we would need to use a var myDougnutChart = new Piechart( { canvas:myCanvas, data:myVinyls, colors:["#fde23e","#f16e23", "#57d9ff","#937e88"], doughnutHoleSize:0.5 } ); myDougnutChart.drawSlices(); And here is the result: Adding Labels and a Chart LegendOur pie chart and doughnut chart look pretty good, but we can make them even better by adding two things:
Usually, values associated with the slices are represented as percentage values calculated as For example, in the case of our sample data, vinyls with classical music would represent approximately How do we calculate the
We will apply these two formulas to place the text halfway along the pie chart radius
and halfway around the angle for each pie slice. To do this, we need to add another method called drawLabels() { var colorIndex = 0; var startAngle = -Math.PI / 2; for (var categ in this.options.data) { var val = this.options.data[categ]; var sliceAngle = (2 * Math.PI * val) / this.totalValue; var labelX = this.canvas.width / 2 + (this.radius / 2) * Math.cos(startAngle + sliceAngle / 2); var labelY = this.canvas.height / 2 + (this.radius / 2) * Math.sin(startAngle + sliceAngle / 2); if (this.options.doughnutHoleSize) { var offset = (this.radius * this.options.doughnutHoleSize) / 2; labelX = this.canvas.width / 2 + (offset + this.radius / 2) * Math.cos(startAngle + sliceAngle / 2); labelY = this.canvas.height / 2 + (offset + this.radius / 2) * Math.sin(startAngle + sliceAngle / 2); } var labelText = Math.round((100 * val) / this.totalValue); this.ctx.fillStyle = "black"; this.ctx.font = "32px Khand"; this.ctx.fillText(labelText + "%", labelX, labelY); startAngle += sliceAngle; } } The code goes over each slice, calculates the percentage, calculates the position, and uses the And here's how the resulting charts look with the value labels: To complete our chart, the last thing we will add is the chart legend. Our chart
legend will display the categories of our data model and the color used for the corresponding slice. First, we have to make some modifications to our <html> <body> <canvas id="myCanvas"></canvas> <div for="myCanvas"></div> <script type="text/javascript" src="script.js"></script> </body> </html> Then in script.js we add the code that creates the content of the legend element. We do this inside the drawLegend() { let pIndex = 0; let legend = document.querySelector("div[for='myCanvas']"); let ul = document.createElement("ul"); legend.append(ul); for (let ctg of Object.keys(this.options.data)) { let li = document.createElement("li"); li.style.listStyle = "none"; li.style.borderLeft = "20px solid " + this.colors[pIndex % this.colors.length]; li.style.padding = "5px"; li.textContent = ctg; ul.append(li); pIndex++; } } The code looks for a Our charts will also have a title to describe what the chart is supposed to show us. We can do that by adding another method called drawTitle() { this.ctx.save(); this.ctx.textBaseline = "bottom"; this.ctx.textAlign = this.titleOptions.align; this.ctx.fillStyle = this.titleOptions.fill; this.ctx.font = `${this.titleOptions.font.weight} ${this.titleOptions.font.size} ${this.titleOptions.font.family}`; let xPos = this.canvas.width / 2; if (this.titleOptions.align == "left") { xPos = 10; } if (this.titleOptions.align == "right") { xPos = this.canvas.width - 10; } this.ctx.fillText(this.options.seriesName, xPos, this.canvas.height); this.ctx.restore(); } One more thing that we can do for our own convenience is to define a draw() { this.drawSlices(); this.drawLabels(); this.drawTitle(); this.drawLegend(); } We also need to make a change to the way we call the drawing of our pie chart like this: var myPiechart = new PieChart({ canvas: myCanvas, seriesName: "Vinyl records", padding: 40, doughnutHoleSize: 0.4, data: { "Classical Music": 16, "Alternative Rock": 12, "Pop": 18, "Jazz": 32 }, colors: ["#80DEEA", "#FFE082", "#FFAB91", "#CE93D8"], titleOptions: { align: "center", fill: "black", font: { weight: "bold", size: "18px", family: "Lato" } } }); myPiechart.draw(); And here is the resulting chart and chart legend: CongratulationsWe have seen that drawing charts using the HTML5 canvas is actually not that hard. It only requires a bit of math and a bit of JavaScript knowledge. You now have everything you need to draw your own pie charts and doughnut charts. If you want a quick and easy solution for creating not only pie charts and doughnut charts but also loads of other types of charts, you can download the Infographic Charts and Graphics HTML Tags Library or its WordPress plugin counterpart Charts and Graphs WordPress Visual Designer. |