Hello everyone I am a newbie in using chart.js package, is there a way I can create is king of chart?
Asked
Active
Viewed 335 times
0

pinkywest
- 25
- 8
-
what **data** should be displayed? what do the arrows mean? should the chart be static? Have you tried something? is the answer "Yes, there is" or "No, there is no way" enough? please provide more details. Thank you :) – winner_joiner Dec 07 '22 at 10:30
-
did you checkout this question & anwser https://stackoverflow.com/a/57992288/1679286 – winner_joiner Dec 07 '22 at 10:32
-
@winner_joiner the arrow point to the percentage value, the rest in the pie chart is a static data value for bad (red part 0-20%), Okay (yellow part 21 - 70%) and Good (green part 71 - 100%) – pinkywest Dec 08 '22 at 06:54
1 Answers
1
Yes, it is possible.
- There might be already a plugin, that can achieve this (but I don't know any, but I didn't really look), so you could look for one,
- Or you could simply write your own plugin, with a few lines of code
Here a demo, how I would do this, with an inline plugin:
(three charts with 3 different percentages)
var arrowPlugin = {
id: 'arrowPlugin',
afterDraw: (chart, args, options) => {
const { ctx } = chart;
let midX = chart.width / 2;
let midY = chart.height;
let arrowLength = chart.height / 2;
let text = `${options.value * 100}%`;
let textSize = ctx.measureText(text);
ctx.save();
ctx.save();
ctx.translate(midX, midY);
ctx.rotate( (Math.PI * options.value) - Math.PI /2);
ctx.strokeStyle = options.arrowColor;
ctx.fillStyle = options.arrowColor;
ctx.lineCap = 'butt';
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(0, - arrowLength * 3 / 4 + 3)
ctx.lineTo(0, - arrowLength * 6 / 4);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(0, - arrowLength * 6 / 4 - 4)
ctx.lineTo(5, - arrowLength * 6 / 4 + 10)
ctx.lineTo(-5, - arrowLength * 6 / 4 + 10)
ctx.closePath();
ctx.fill()
ctx.fillStyle = options.triangleColor;
ctx.beginPath();
ctx.moveTo(0, -midY + 25)
ctx.lineTo(-10, -midY + 10)
ctx.lineTo(10, -midY + 10)
ctx.closePath()
ctx.fill();
ctx.restore();
ctx.fillStyle = options.textColor;
ctx.font = "50px Arial";
ctx.fillText(text, midX - textSize.width * 1.5, midY - 25);
ctx.restore();
},
defaults: {
// set here the percentage
value:.50,
arrowColor: 'black',
textColor: 'black',
triangleColor: 'black'
}
}
var options1 = {
type: 'doughnut',
data: {
datasets: [{
data: [20, 50, 30],
backgroundColor: [
'rgba(231, 76, 60, 1)',
'rgba(255, 164, 46, 1)',
'rgba(46, 204, 113, 1)'
],
borderColor: [
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)'
],
borderWidth: 0
}]},
options: {
cutout: 33,
rotation: -90,
circumference: 180,
maintainAspectRatio: false,
legend: { display: false },
plugins:{
tooltip: { enabled: false },
}
},
plugins:[arrowPlugin]
}
var options2 = {
type: 'doughnut',
data: {
datasets: [{
data: [20, 50, 30],
backgroundColor: [
'rgba(231, 76, 60, 1)',
'rgba(255, 164, 46, 1)',
'rgba(46, 204, 113, 1)'
],
borderColor: [
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)'
],
borderWidth: 0
}]},
options: {
cutout: 33,
rotation: -90,
circumference: 180,
maintainAspectRatio: false,
legend: { display: false },
plugins:{
tooltip: { enabled: false },
// override default percentage
arrowPlugin: { value: .20 }
}
},
plugins:[arrowPlugin]
}
var options3 = {
type: 'doughnut',
data: {
datasets: [{
data: [20, 50, 30],
backgroundColor: [
'rgba(231, 76, 60, 1)',
'rgba(255, 164, 46, 1)',
'rgba(46, 204, 113, 1)'
],
borderColor: [
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)',
'rgba(255, 255, 255 ,1)'
],
borderWidth: 0
}]},
options: {
cutout: 33,
rotation: -90,
circumference: 180,
maintainAspectRatio: false,
legend: { display: false },
plugins:{
tooltip: { enabled: false },
// override default percentage
arrowPlugin: { value: .70 }
}
},
plugins:[arrowPlugin]
}
const chart1 = document.getElementById('chart1')
new Chart(chart1, options1);
const chart2 = document.getElementById('chart2')
new Chart(chart2, options2);
const chart3 = document.getElementById('chart3')
new Chart(chart3, options3);
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div style="width:500px;height:184px">
<canvas id="chart1" width="500" height="184"></canvas>
<canvas id="chart2" width="500" height="184"></canvas>
<canvas id="chart3" width="500" height="184"></canvas>
<div>
the percentage is currently set in the inline plugin-options, default value is set to .5 = 50% (valid range 0 - 1 = 0% - 100%).

winner_joiner
- 12,173
- 4
- 36
- 61
-
1thank you @winner_joiner, is there a way that the triangle follow the arrow direction? – pinkywest Dec 09 '22 at 03:59
-
@pinkywest sure just move the trinangle code block over the `ctx.restore()` line an tweak the coordinates. _(I updated the demo code)_ – winner_joiner Dec 09 '22 at 07:36