[Chartjs]-How to create a simple Gauge with ChartJS v3?

17๐Ÿ‘

โœ…

As per the migration guide in v3 the rotation and circumference options are in degrees instead of in radians, if you place them as degrees it works just fine:

var options = {
  type: 'doughnut',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
      label: '# of Votes',
      data: [12, 19, 3, 5, 2, 3],
      backgroundColor: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"]
    }]
  },
  options: {
    rotation: 270, // start angle in degrees
    circumference: 180, // sweep angle in degrees
  }
}

var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>

3๐Ÿ‘

Here is an example that I use and it works fine with version 3.5.1

HTML

<div class="chartBox">
  <canvas id="gauge"></canvas>
</div>

CSS

.chartBox {
  width: 400px;
  padding: 20px;
  border-radius: 20px;
}

JavaScript

// setup
const data = {
  labels: ["Safe", "Risky", "High Risk"],
  datasets: [
    {
      label: "Gauge",
      data: [100, 65, 35],
      backgroundColor: [
        "rgba(75, 192, 192, 0.8)",
        "rgba(255, 206, 86, 0.8)",
        "rgba(255, 26, 104, 0.8)",
      ],
      needleValue: 50,
      borderColor: "white",
      borderWidth: 2,
      cutout: "95%",
      circumference: 180,
      rotation: 270,
      borderRadius: 5,
    },
  ],
};

//gaugeNeedle
const gaugeNeedle = {
  id: "gaugeNeedle",
  afterDatasetDraw(chart, args, options) {
    const {
      ctx,
      config,
      data,
      chartArea: { top, right, bottom, left, width, height },
    } = chart;
    ctx.save();
    const needleValue = data.datasets[0].needleValue;
    const dataTotal = data.datasets[0].data.reduce((a, b) => a + b, 0);

    if (needleValue <= 100) {
      var angle = Math.PI + (1 / 200) * needleValue * Math.PI;
      console.log(angle);
    } else if (needleValue <= 10000) {
      var angle =
        Math.PI +
        (1 / 200) * 100 * Math.PI +
        ((1 / 200) * needleValue * Math.PI * 65) / 10000;
    } else if (needleValue <= 1000000) {
      var angle =
        Math.PI +
        (1 / 200) * 100 * Math.PI +
        ((1 / 200) * 10000 * Math.PI * 65) / 10000 +
        ((1 / 200) * needleValue * Math.PI * 35) / 1000000;
    } else {
      var angle = 0;
    }

    const cx = width / 2;
    const cy = chart._metasets[0].data[0].y;

    //needle
    ctx.translate(cx, cy);
    ctx.rotate(angle);
    ctx.beginPath();
    ctx.moveTo(0, -2);
    ctx.lineTo(height - ctx.canvas.offsetTop - 160, 0); // change 160 value if the needle size gets changed
    ctx.lineTo(0, 2);
    ctx.fillStyle = "#444";
    ctx.fill();
    //needle dot
    ctx.translate(-cx, -cy);
    ctx.beginPath();
    ctx.arc(cx, cy, 5, 0, 10);
    ctx.fill();
    ctx.restore();

    //text
    ctx.font = "20px Ubuntu";
    ctx.fillStyle = "#444";
    ctx.fillText(needleValue + " CPM", cx, cy + 50);
    ctx.font = "10px Ubuntu";
    ctx.fillText(0, 5, cy + 20);
    ctx.fillText(100, cx, 90);
    ctx.fillText("10k", cx + 185, 200); // change values if the position gets changed
    ctx.fillText("1M", cx + 193, 320); // change values if the position gets changed
    ctx.textAlign = "center";
    ctx.restore();
  },
};
// config
const config = {
  type: "doughnut",
  data,
  options: {
    plugins: {
      legend: {
        display: false,
      },
      tooltip: {
        yAlign: "bottom",
        displayColors: false,
        callbacks: {
          label: function (tooltipItem, data, value) {
            return tooltipItem.label;
          },
        },
      },
    },
  },
  plugins: [gaugeNeedle],
};

// render init block
const myChart = new Chart(document.getElementById("gauge"), config);

Note: This works fine when the width is set 400px. If you change this value other parameters need to be changed accordingly. However, The affected locations are commented in the JavaScript.

Leave a comment