Chartjs-Is there a way to give a pie chart in chart.js a different color outer border than the border color between segments?

0👍

You can use a custom inline plugin for this in combination with a scriptable option for the borderWidth itself.

Plugin:

{
    id: 'circleAroundPieDoughnut',
    beforeDatasetsDraw: (chart, args, options) => {
      if (chart.data.datasets[0].data.length > 1) return;

      const {
        ctx,
        canvas
      } = chart;
      const {
        top,
        left,
        width,
        height
      } = chart.chartArea;
      const x = left + width / 2;
      const y = top + height / 2;
      const outerRadius = chart._metasets[0].data[0].outerRadius;

      ctx.beginPath()
      ctx.arc(x, y, outerRadius + ((options.width || 0) / 2), 0, 2 * Math.PI);
      ctx.lineWidth = options.width || 1
      ctx.strokeStyle = options.color || '#000';
      ctx.stroke();
    }
  }

Live Example:

var options = {
  type: 'doughnut',
  data: {
    labels: ["Red"],
    datasets: [{
      label: '# of Votes',
      data: [12],
      borderWidth: (ctx) => (ctx.chart.data.datasets[0].data.length === 1 ? 0 : 3),
      backgroundColor: ["Red"]
    }]
  },
  options: {
    radius: '98%',
    plugins: {
      legend: {
        display: false
      },
      circleAroundPieDoughnut: {
        width: 6, // Width of the border, defaults to 1
        color: 'blue' // Color of the border, defaults to black
      }
    }
  },
  plugins: [{
    id: 'circleAroundPieDoughnut',
    beforeDatasetsDraw: (chart, args, options) => {
      if (chart.data.datasets[0].data.length > 1) return;

      const {
        ctx,
        canvas
      } = chart;
      const {
        top,
        left,
        width,
        height
      } = chart.chartArea;
      const x = left + width / 2;
      const y = top + height / 2;
      const outerRadius = chart._metasets[0].data[0].outerRadius;

      ctx.beginPath()
      ctx.arc(x, y, outerRadius + ((options.width || 0) / 2), 0, 2 * Math.PI);
      ctx.lineWidth = options.width || 1
      ctx.strokeStyle = options.color || '#000';
      ctx.stroke();
    }
  }]
}

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.3.0/chart.js"></script>
</body>

Fiddle: https://jsfiddle.net/Leelenaleee/us52em7f/18/

0👍

That’s brilliant – I’ve implemented this, but seem to be getting a slightly boxy circle that extends beyond the bounds of the canvas in circumstances where the function draws the border where there’s only one datapoint. Any ideas on how to fix?

    function makepie(a,b,c,d){
 if (b <= 0) {n = 'n'} else {n = 'y'}
  if (c <= 0) {o = 'n'} else {o = 'y'}
  if (d <= 0) {p = 'n'} else {p = 'y'}
  q = n + o + p
  if (q == 'nnn') {s = [a];r = ['Indianred'];u = ['Emails']}
  if (q == 'yyy') {s = [a, b, c, d];r = ['Indianred', 'salmon', 'pink', 'mistyrose'];u = ['Emails','Calls','Meetings','Working']}
  if (q == 'ynn') {s = [a, b];r = ['Indianred', 'salmon'];u = ['Emails','Calls']}
  if (q == 'nyn') {s = [a, c];r = ['Indianred', 'pink', ];u = ['Emails','Working']}
  if (q == 'nny') {s = [a, d];r = ['Indianred', 'mistyrose'];u = ['Emails','Working']}
  if (q == 'yyn') {s = [a, b, c];r = ['Indianred', 'salmon', 'pink'];u = ['Emails','Calls','Meetings']}
  if (q == 'yny') {s = [a, b, d];r = ['Indianred', 'salmon', 'mistyrose'];u = ['Emails','Calls','Working']}
  if (q == 'nyy') {s = [a, c, d];r = ['Indianred', 'pink', 'mistyrose'];u = ['Emails','Meetings','Working']}
  var options = {
    type: 'pie',
    data: {
      labels: u,
      datasets: [{
        data: s,
        borderColor: '#6f6f6f',
        borderWidth: (ctx) => (ctx.chart.data.datasets[0].data.length === 1 ? 0 : 3),
        backgroundColor: r
      }]
    },
    options: {
        hover: {mode: null},
        animation: {duration: (Math.floor(Math.random() * 30) + 20) * 100},
        legend: {display: false,labels: {display: false}},
        rotation: (Math.floor(Math.random() * 5)+1),
        tooltips: {enabled: false},
        plugins: {
        legend: {display: false},
        circleAroundPieDoughnut: {
          width: 3,
          color: '#6f6f6f'
        }
      }
    },
    plugins: [{
      id: 'circleAroundPieDoughnut',
      beforeDatasetsDraw: (chart, args, options) => {
        if (chart.data.datasets[0].data.length > 1) return;

        var {
          ctx,
          canvas
        } = chart;
        var {
          top,
          left,
          width,
          height
        } = chart.chartArea;
        var x = left + width / 2;
        var y = top + height / 2;
        var outerRadius = chart._metasets[0].data[0].outerRadius;

        ctx.beginPath()
        ctx.arc(x, y, outerRadius + ((options.width || 0) / 2), 0, 2 * Math.PI);
        ctx.lineWidth = options.width || 1
        ctx.strokeStyle = options.color || '#000';
        ctx.stroke();
      }
    }],

  }

  var ctx = document.getElementById('chartJSContainer').getContext('2d');
  new Chart(ctx, options);
}

Fiddle: https://jsfiddle.net/theboyler/mp016df2/17/

Leave a comment