Home > database >  Chart.js Radial chart with arrow using Vue.js
Chart.js Radial chart with arrow using Vue.js

Time:12-09

Hello everyone I am a newbie in using chart.js package, is there a way I can create is king of chart?enter image description here

CodePudding user response:

Yes, it is possible.

  1. Maybe there is a plugin out there,
  2. Or you could write a own plugin one with a few lines of code

Here a demo, how I would do this, with an inline plugin:

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.restore();
        
        ctx.fillStyle = options.triangleColor;
        ctx.beginPath();
        ctx.moveTo(chart.width/2, 25)
        ctx.lineTo(chart.width/2 - 8, 10)
        ctx.lineTo(chart.width/2   8, 10)
        ctx.closePath()
        ctx.fill();
        
        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).

  • Related