I use this doughnut chart from chartjs in vue using vue-chartjs.
By default the doughnut chart when there are no data or all values are empty it show nothing. Is there a way to show doughnut chart with custom color when there are no values or all the values are 0 in the dataset in the doughnut rings.
Desired behaviour: A doughnut chart with custom color when no data. Like here in this link doughnut-empty-state they only provided with a circle. Instead want full doughnut with custom color input when empty. How Should I do that?
Implementation:
<template>
<Doughnut
id="my-chart-id"
:chartOptions="getChartOptions"
:chartData="getChartData"
:plugins="[defaultBackground]"
/>
</template>
<script>
import { Doughnut } from 'vue-chartjs';
import { Chart as ChartJS, ArcElement } from 'chart.js';
ChartJS.register(ArcElement);
export default {
name: 'DoughnutChart',
components: { Doughnut },
props: ['chartData', 'options', 'theme', 'mspDomain', 'rootDomain'],
data() {
return {
defaultBackground: {
id: 'custom_canvas_background_color',
afterDraw: function(chart) {
const {datasets} = chart.data;
const {color, width, radiusDecrease} = options;
let hasData = false;
for (let i = 0; i < datasets.length; i += 1) {
const dataset = datasets[i];
hasData |= dataset.data.length > 0;
}
if (!hasData) {
const {chartArea: {left, top, right, bottom}, ctx} = chart;
const centerX = (left + right) / 2;
const centerY = (top + bottom) / 2;
const r = Math.min(right - left, bottom - top) / 2;
ctx.beginPath();
ctx.lineWidth = width || 2;
ctx.strokeStyle = color || 'rgba(255, 128, 0, 0.5)';
ctx.arc(centerX, centerY, (r - radiusDecrease || 0), 0, 2 * Math.PI);
ctx.stroke();
}
}
}
};
},
computed: {
getChartData() {
return this.chartData;
},
getChartOptions() {
return this.options;
}
}
};
</script>
<style></style>
Here it just paints a circle instead of whole doughnut.
I created the doughnut chart in afterDraw plugin with all the calculation and radius as per how I wanted. I modified the code from this reference given in chartjs for empty data.
Here you can change radius, color according to your requirements.
<template>
<Doughnut
id="my-chart-id"
:chartOptions="getChartOptions"
:chartData="getChartData"
:plugins="[defaultBackground]"
/>
</template>
<script>
import { Doughnut } from 'vue-chartjs';
import { Chart as ChartJS, ArcElement } from 'chart.js';
ChartJS.register(ArcElement);
export default {
name: 'DoughnutChart',
components: { Doughnut },
props: ['chartData', 'options'],
data() {
return {
defaultBackground: {
id: 'custom_canvas_background_color',
afterDraw: function(chart) {
let totalData = chart.config.data.datasets[0].data.reduce(function(
a,
b
) {
return a + b;
},
0);
if (totalData === 0) {
const {
chartArea: { left, top, right, bottom },
ctx
} = chart;
ctx.save(); // Save the current canvas state
// Calculate the center of the chart
const centerX = (left + right) / 2;
const centerY = (top + bottom) / 2;
// Calculate the radii of the inner and outer circles of the doughnut
const outerRadius = Math.min(right - left, bottom - top) / 2;
const innerRadius = outerRadius - 45; // Adjust this value as needed
// Calculate the positions for the starting and ending points of the line
const lineStartX = centerX;
const lineStartY = centerY - outerRadius;
const lineEndX = centerX;
const lineEndY = centerY - innerRadius;
// Draw the outer arc (grey doughnut ring)
ctx.beginPath();
ctx.arc(centerX, centerY, outerRadius, 0, 2 * Math.PI);
ctx.fillStyle = 'rgba(216, 216, 216, 1)';
ctx.fill();
// Draw the inner arc (to clear the inner circle)
ctx.beginPath();
ctx.arc(centerX, centerY, innerRadius, 0, 2 * Math.PI);
ctx.fillStyle = 'rgba(255, 255, 255, 1)'; // Fill with white to clear the inner circle
ctx.fill();
// Draw the white line break from outer circle to inner circle
ctx.beginPath();
ctx.moveTo(lineStartX, lineStartY);
ctx.lineTo(lineEndX, lineEndY);
ctx.lineWidth = 2; // Adjust the line width as needed
ctx.strokeStyle = 'rgba(255, 255, 255, 1)'; // White color
ctx.stroke();
ctx.restore(); // Restore the canvas state
}
}
}
};
},
computed: {
getChartData() {
return this.chartData;
},
getChartOptions() {
return this.options;
}
}
};
</script>
<style></style>