[Chartjs]-How to draw a needle on a custom donut chart and add datapoints to the needle?

3👍

You can use the Plugin Core API that offers a range of hooks that may be used for performing custom code. The afterDraw hook may be used to draw the needle directly on the canvas through CanvasRenderingContext2D.

First we need to define the property needleValue inside the dataset.

datasets: [{
  data: [35, 35, 35],
  needleValue: 580,
  ...
}],

The solution is based on the code sample provided by Konstantin S.. Please have a look at your amended code below.

new Chart('oilChart', {
  type: 'doughnut',
  plugins: [{
    afterDraw: chart => {
      var needleValue = chart.chart.config.data.datasets[0].needleValue;
      var dataTotal = chart.chart.config.data.datasets[0].data.reduce((a, b) => a + b, 0);
      var angle = Math.PI + (1 / dataTotal * needleValue * Math.PI);
      var ctx = chart.chart.ctx;
      var cw = chart.chart.canvas.offsetWidth;
      var ch = chart.chart.canvas.offsetHeight;
      var cx = cw / 2;
      var cy = ch - 6;

      ctx.translate(cx, cy);
      ctx.rotate(angle);
      ctx.beginPath();
      ctx.moveTo(0, -3);
      ctx.lineTo(ch - 20, 0);
      ctx.lineTo(0, 3);
      ctx.fillStyle = 'rgb(0, 0, 0)';
      ctx.fill();
      ctx.rotate(-angle);
      ctx.translate(-cx, -cy);
      ctx.beginPath();
      ctx.arc(cx, cy, 5, 0, Math.PI * 2);
      ctx.fill();
    }
  }],
  data: {
    labels: [],
    datasets: [{
      data: [35, 35, 35],
      needleValue: 27,
      backgroundColor: [
        'rgba(255, 99, 132, 0.2)',
        'rgba(255, 206, 86, 0.2)',
        'rgba(63, 191, 63, 0.2)'
      ]
    }]
  },
  options: {
    layout: {
      padding: {
        bottom: 3
      }
    },
    rotation: -Math.PI,
    cutoutPercentage: 30,
    circumference: Math.PI,
    legend: {
      position: 'left'
    },
    animation: {
      animateRotate: false,
      animateScale: true
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="oilChart" height="80"></canvas>

Leave a comment