Chart.js 圆角甜甜圈

2022-01-22 00:00:00 canvas charts javascript chart.js

我用 Chart.js 创建了一个圆环图,我希望它的两端都有圆形边缘.我希望它是这样的:

但我有这样的,边缘锋利:

我找到的最好的答案是:

Chart.defaults.RoundedDoughnut = Chart.helpers.clone(Chart.defaults.doughnut);Chart.controllers.RoundedDoughnut = Chart.controllers.doughnut.extend({绘制:功能(轻松){var ctx = this.chart.ctx;var easingDecimal = 轻松 ||1个;var arcs = this.getMeta().data;Chart.helpers.each(arcs, function(arc, i) {arc.transition(easingDecimal).draw();var pArc = 弧[i === 0 ?arcs.length - 1 : i - 1];var pColor = pArc._view.backgroundColor;var vm = arc._view;变量半径 = (vm.outerRadius + vm.innerRadius)/2;var 厚度 = (vm.outerRadius - vm.innerRadius)/2;var startAngle = Math.PI - vm.startAngle - Math.PI/2;变角 = Math.PI - vm.endAngle - Math.PI/2;ctx.save();ctx.translate(vm.x, vm.y);ctx.fillStyle = i === 0 ?vm.backgroundColor : pColor;ctx.beginPath();ctx.arc(半径 * Math.sin(startAngle), 半径 * Math.cos(startAngle), 厚度, 0, 2 * Math.PI);ctx.fill();ctx.fillStyle = vm.backgroundColor;ctx.beginPath();ctx.arc(半径 * Math.sin(角度), 半径 * Math.cos(角度), 厚度, 0, 2 * Math.PI);ctx.fill();ctx.restore();});}});window.onload = 函数(){新图表(document.getElementById('usersChart'),{类型:'圆形甜甜圈',数据   : {数据集:[{数据:[40、20、20、20],背景颜色: ['#e77099','#5da4e7','#8f75e7','#8fe768'],边框宽度:0}]},选项: {剪裁百分比:70}});};

<script src="https://github.com/chartjs/Chart.js/releases/download/v2.9.3/Chart.min.js"></脚本><link rel="stylesheet" href="https://github.com/chartjs/Chart.js/releases/download/v2.9.3/Chart.min.css"><div style="width: 200px; height: 200px;"><canvas id="usersChart" width="1" height="1"></canvas></div>

I created a donut chart with Chart.js and I want it to have rounded edges at both ends. I want it to be like this:

But I have it like this, with sharp edges:

The best I found was this answer: How to put rounded corners on a Chart.js Bar chart, but it is for bar charts, and I have no clue of how to adapt it for doughnuts..

Here is my code:

HTML

<div class="modal-div-canvas js-chart">
  <div class="chart-canvas">
     <canvas id="openedCanvas" width="1" height="1"></canvas>
        <div class="chart-background"></div>
            <span class="chart-unique-value">
                 <span class="js-count">
                    85
                 </span>
                 <span class="cuv-percent">%</span>
            </span>
        </div>
  </div>

JS

var deliveredData = {
        labels: [
            "Value"
        ],
        datasets: [
            {
                data: [85, 15)],
                backgroundColor: [
                    "#3ec556",
                    "rgba(0,0,0,0)"
                ],
                hoverBackgroundColor: [
                    "#3ec556",
                    "rgba(0,0,0,0)"
                ],
                borderWidth: [
                    0, 0
                ]
            }]
    };

    var deliveredOpt = {
        cutoutPercentage: 88,
        animation: {
            animationRotate: true,
            duration: 2000
        },
        legend: {
            display: false
        },
        tooltips: {
            enabled: false
        }
    };

   var chart = new Chart($('#openedCanvas'), {
        type: 'doughnut',
        data: deliveredData,
        options: deliveredOpt
    });
}};

Someone know how to do this?

解决方案

I made some changes in the @potatopeeling snippet, I made compatibility with the newer (2.9.x) version of chart.js also fixed where the "startArc" should be rendered and the color from the previous segment to match this "startArc", so we can have more than 2 segments. This is the result:

Chart.defaults.RoundedDoughnut    = Chart.helpers.clone(Chart.defaults.doughnut);
Chart.controllers.RoundedDoughnut = Chart.controllers.doughnut.extend({
    draw: function(ease) {
        var ctx           = this.chart.ctx;
        var easingDecimal = ease || 1;
        var arcs          = this.getMeta().data;
        Chart.helpers.each(arcs, function(arc, i) {
            arc.transition(easingDecimal).draw();

            var pArc   = arcs[i === 0 ? arcs.length - 1 : i - 1];
            var pColor = pArc._view.backgroundColor;

            var vm         = arc._view;
            var radius     = (vm.outerRadius + vm.innerRadius) / 2;
            var thickness  = (vm.outerRadius - vm.innerRadius) / 2;
            var startAngle = Math.PI - vm.startAngle - Math.PI / 2;
            var angle      = Math.PI - vm.endAngle - Math.PI / 2;

            ctx.save();
            ctx.translate(vm.x, vm.y);

            ctx.fillStyle = i === 0 ? vm.backgroundColor : pColor;
            ctx.beginPath();
            ctx.arc(radius * Math.sin(startAngle), radius * Math.cos(startAngle), thickness, 0, 2 * Math.PI);
            ctx.fill();

            ctx.fillStyle = vm.backgroundColor;
            ctx.beginPath();
            ctx.arc(radius * Math.sin(angle), radius * Math.cos(angle), thickness, 0, 2 * Math.PI);
            ctx.fill();

            ctx.restore();
        });
    }
});

window.onload = function() {
    new Chart(document.getElementById('usersChart'), {
        type   : 'RoundedDoughnut',
        data   : {
            datasets: [
                {
                    data           : [40, 20, 20, 20],
                    backgroundColor: [
                        '#e77099',
                        '#5da4e7',
                        '#8f75e7',
                        '#8fe768'
                    ],
                    borderWidth    : 0
                }]
        },
        options: {
            cutoutPercentage: 70
        }
    });
};

<script src="https://github.com/chartjs/Chart.js/releases/download/v2.9.3/Chart.min.js"></script>
<link rel="stylesheet" href="https://github.com/chartjs/Chart.js/releases/download/v2.9.3/Chart.min.css">
<div style="width: 200px; height: 200px;">
<canvas id="usersChart" width="1" height="1"></canvas>
</div>

相关文章