Check Out the Chart.js Course: Chart.js, The Missing Manual Course
Categories
Uncategorized

How to show all data points on radar chart using Chart.js 4

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 method beforeDatasetsDraw.
  • 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 the chart object.
  • Variables like xCenter, yCenter, drawingArea, segmentDrawingArea, and angle 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 and labelLength 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:

  1. 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>
en_USEnglish