1👍
I solved it by using a duplicate Donut (2nd canvas) with a value of 100, no animation and my desired background-color, and positioned it absolute, underneath the 1st one.
However, this is a nasty trick, and very inefficient, so I’m still hoping for a correct answer.
11👍
Thought I’d post a recent solution that worked for me, using v2.1.0 which introduced plugins.
Chart with no value displaying a background vs chart with value covering the background, only the main chart will animate, the background is just a simple arc:
I first registered a plugin per their docs:
var radiusBackground = function() {
var self = this;
self.draw = function(chartInstance) {
if(chartInstance.options.radiusBackground) {
var x = chartInstance.chart.canvas.clientWidth / 2,
y = chartInstance.chart.canvas.clientHeight / 2,
ctx = chartInstance.chart.ctx;
ctx.beginPath();
ctx.arc(x, y, chartInstance.outerRadius - (chartInstance.radiusLength / 2), 0, 2 * Math.PI);
ctx.lineWidth = chartInstance.radiusLength;
ctx.strokeStyle = chartInstance.options.radiusBackground.color || '#d1d1d1';
ctx.stroke();
}
};
// see http://www.chartjs.org/docs/#advanced-usage-creating-plugins for plugin interface
return {
beforeDatasetsDraw: self.draw,
onResize: self.draw
}
};
// Register with Chart JS
Chart.plugins.register(new radiusBackground());
The singleton syntax was just to be able to reduce duplication and use the same draw
method for multiple plugin events.
Then I used my new registered plugin like so:
var chartElement = document.getElementById('doughnut-chart');
var chart = new Chart(chartElement, {
type: 'doughnut',
options: {
// Here is where we enable the 'radiusBackground'
radiusBackground: {
color: '#d1d1d1' // Set your color per instance if you like
},
cutoutPercentage: 90,
title: {
display: false,
},
legend: {
display: false,
},
},
data: {
labels: ["Type 1", "Type 2", "Type 3"],
datasets: [{
data: [2, 5, 1],
backgroundColor: ["#a3c7c9","#889d9e","#647678"],
borderWidth: 0,
hoverBackgroundColor: ["#96b7b9","#718283","#5c6b6d"]
}]
}
});
4👍
I used @Jonlunsford ‘s code, but it didn’t work when I upgraded ChartJS to 3.x.
According to the Migration Guide, It says
Chart.innerRadius now lives on doughnut, pie, and polarArea controllers
So I changed the code to:
import { Chart, DoughnutController } from 'chart.js'
type DoughnutChartBackgroundPluginOptions = {
enabled: boolean
color: string
}
function handler(chart: Chart<'doughnut'>, args, options: DoughnutChartBackgroundPluginOptions) {
const { ctx, width, height } = chart
const { innerRadius } = chart.getDatasetMeta(chart.data.datasets.length - 1).controller as DoughnutController
const { outerRadius } = chart.getDatasetMeta(0).controller as DoughnutController
const radiusLength = outerRadius - innerRadius
if (options.enabled) {
const x = width / 2,
y = height / 2
ctx.beginPath()
ctx.arc(x, y, outerRadius - radiusLength / 2, 0, 2 * Math.PI)
ctx.lineWidth = radiusLength
ctx.strokeStyle = options.color
ctx.stroke()
}
}
export default {
id: 'doughnutChartBackground',
beforeDatasetsDraw: handler,
}
Then, when creating a chart, you can use the options as follows:
...
plugins: {
legend: {
display: false,
},
doughnutBackground: {
enabled: true,
color: '#E4E6E6',
},
...
},
0👍
Probably there’s no way how you can do it in the canvas element.
I would place a absolute positioned element beyond the canvas. here’s an example:
.fakeCircle {
position: absolute;
z-index: 0;
border-radius: 90px;
-webkit-border-radius: 90px;
-moz-border-radius: 90px;
background-color: #dadce8;
width: 50px;
height: 50px;
top: 12px;
left: 12px;
}
.fakeCircle:after {
position: absolute;
z-index: 0;
border-radius: 50px;
-webkit-border-radius: 50px;
-moz-border-radius: 50px;
background-color: #fff;
width: 34px;
height: 34px;
content: "";
}