To add extra datapoints we will be using a custom plugin.
This code defines a Chart.js plugin called subLabels
that is used to draw additional circular sub-labels around a radar chart. Let’s break down the code:
Plugin Definition:
const subLabels = {
id: 'subLabels',
beforeDatasetsDraw(chart, args, plugins) {
// Code for drawing sub-labels
}
};
- The plugin is defined as an object with an
id
property set to ‘subLabels’ and a methodbeforeDatasetsDraw
. - The
beforeDatasetsDraw
method is a hook that is called before the datasets are drawn on the chart.
Drawing Sub-Labels:
const { ctx, data, scales: {r} } = chart;
const xCenter = r.xCenter;
const yCenter = r.yCenter;
const drawingArea = r.drawingArea;
const segmentDrawingArea = r.drawingArea / 6;
const angle = Math.PI / 180;
- The code extracts the chart context (
ctx
), data, and the radial scale (r
) from thechart
object. - Variables like
xCenter
,yCenter
,drawingArea
,segmentDrawingArea
, andangle
are defined for convenience.
Loop for Drawing Circular Sub-Labels:
const tickLength = r.ticks.length - 1;
const labelLength = data.labels.length - 1;
for(let i = 1; i < tickLength; i++) {
for(let j = 0; j <= labelLength; j++) {
// Drawing code for each circular sub-label
}
}
- The code initializes variables
tickLength
andlabelLength
based on the number of ticks and labels in the radar chart. - Two nested loops iterate over the ticks and labels to draw circular sub-labels.
Drawing Each Circular Sub-Label:
ctx.save();
ctx.translate(xCenter, yCenter);
ctx.rotate(angle * 72 * j);
ctx.beginPath();
ctx.fillStyle = data.labels[j];
ctx.arc(0, -segmentDrawingArea * i, 10, angle * 0, angle * 360, false);
ctx.fill();
ctx.fillStyle = 'white';
ctx.font = 'bold 12px sans-serif';
ctx.textAlign = 'center';
ctx.fillText(i, 0, -segmentDrawingArea * i);
ctx.restore();
- Inside the nested loops, the code saves the current canvas state, translates to the radar chart center, and rotates the canvas based on the angle.
- It then draws a filled circular sub-label with a color from
data.labels
. - The label text (
i
) is drawn in white above the circular sub-label.
End of Drawing Logic:
- The entire drawing logic is enclosed within the
beforeDatasetsDraw
method, which ensures that these circular sub-labels are drawn before the main datasets of the radar chart.
In summary, this Chart.js plugin adds circular sub-labels around a radar chart to provide additional information or visual cues.
See full code below:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Getting Started with Chart JS with www.chartjs3.com</title>
<style>
* {
margin: 0;
padding: 0;
font-family: sans-serif;
}
.chartMenu {
width: 100vw;
height: 40px;
background: #1A1A1A;
color: rgba(54, 162, 235, 1);
}
.chartMenu p {
padding: 10px;
font-size: 20px;
}
.chartCard {
width: 100vw;
height: calc(100vh - 40px);
background: rgba(54, 162, 235, 0.2);
display: flex;
align-items: center;
justify-content: center;
}
.chartBox {
width: 700px;
padding: 20px;
border-radius: 20px;
border: solid 3px rgba(54, 162, 235, 1);
background: white;
}
</style>
</head>
<body>
<div class="chartMenu">
<p>WWW.CHARTJS3.COM (Chart JS <span id="chartVersion"></span>)</p>
</div>
<div class="chartCard">
<div class="chartBox">
<canvas id="myChart"></canvas>
</div>
</div>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/chart.js/dist/chart.umd.min.js"></script>
<script>
// setup
const data = {
labels: ['Red', 'Orange', 'Green', 'Blue', 'Brown'],
// datasets: [{
// label: 'Growth Chart',
// data: [1, 2, 3 ,4 ,5],
// backgroundColor: [
// 'rgba(0, 0, 0, 0.2)'
// ],
// borderColor: [
// 'rgba(0, 0, 0, 1)'
// ],
// borderWidth: 1,
// }]
};
const subLabels = {
id: 'subLabels',
beforeDatasetsDraw(chart, args, plugins) {
const { ctx, data, scales: {r} } = chart;
console.log(r)
const xCenter = r.xCenter;
const yCenter = r.yCenter;
const drawingArea = r.drawingArea;
const segmentDrawingArea = r.drawingArea / 6;
const angle = Math.PI / 180;
const tickLength = r.ticks.length - 1;
const labelLength = data.labels.length - 1;
for(let i = 1; i < tickLength; i++) {
for(let j = 0; j <= labelLength; j++) {
ctx.save();
ctx.translate(xCenter, yCenter);
ctx.rotate(angle * 72 * j)
ctx.beginPath();
ctx.fillStyle = data.labels[j];
ctx.arc(0, -segmentDrawingArea * i, 10, angle * 0, angle * 360, false);
ctx.fill();
ctx.fillStyle = 'white';
ctx.font = 'bold 12px sans-serif';
ctx.textAlign = 'center';
ctx.fillText(i, 0, -segmentDrawingArea * i)
ctx.restore();
}
}
}
}
// config
const config = {
type: 'radar',
data,
options: {
scales: {
r: {
min: 0,
max: 6,
ticks: {
callback: ((value, index, ticks) => {
return '';
})
}
}
}
},
plugins: [subLabels]
};
// render init block
const myChart = new Chart(
document.getElementById('myChart'),
config
);
// Instantly assign Chart.js version
const chartVersion = document.getElementById('chartVersion');
chartVersion.innerText = Chart.version;
</script>
</body>
</html>