Chart.js Doughnut with rounded edges

后端 未结 2 1848
借酒劲吻你
借酒劲吻你 2020-12-15 09:23

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

相关标签:
2条回答
  • 2020-12-15 09:27

    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>

    0 讨论(0)
  • 2020-12-15 09:45

    You can extend the chart to do this


    Preview


    Script

    Chart.defaults.RoundedDoughnut = Chart.helpers.clone(Chart.defaults.doughnut);
    Chart.controllers.RoundedDoughnut = Chart.controllers.doughnut.extend({
        draw: function (ease) {
            var ctx = this.chart.chart.ctx;
    
            var easingDecimal = ease || 1;
            Chart.helpers.each(this.getDataset().metaData, function (arc, index) {
                arc.transition(easingDecimal).draw();
    
                var vm = arc._view;
                var radius = (vm.outerRadius + vm.innerRadius) / 2;
                var thickness = (vm.outerRadius - vm.innerRadius) / 2;
                var angle = Math.PI - vm.endAngle - Math.PI / 2;
    
                ctx.save();
                ctx.fillStyle = vm.backgroundColor;
                ctx.translate(vm.x, vm.y);
                ctx.beginPath();
                ctx.arc(radius * Math.sin(angle), radius * Math.cos(angle), thickness, 0, 2 * Math.PI);
                ctx.arc(radius * Math.sin(Math.PI), radius * Math.cos(Math.PI), thickness, 0, 2 * Math.PI);
                ctx.closePath();
                ctx.fill();
                ctx.restore();
            });
        },
    });
    

    and then

    ...
    type: 'RoundedDoughnut',
    ...
    

    Stack Snippet

    Chart.defaults.RoundedDoughnut = Chart.helpers.clone(Chart.defaults.doughnut);
            Chart.controllers.RoundedDoughnut = Chart.controllers.doughnut.extend({
                draw: function (ease) {
                		var ctx = this.chart.chart.ctx;
                    
                    var easingDecimal = ease || 1;
                    Chart.helpers.each(this.getDataset().metaData, function (arc, index) {
                        arc.transition(easingDecimal).draw();
    
                        var vm = arc._view;
                        var radius = (vm.outerRadius + vm.innerRadius) / 2;
                        var thickness = (vm.outerRadius - vm.innerRadius) / 2;
                        var angle = Math.PI - vm.endAngle - Math.PI / 2;
                        
                        ctx.save();
                        ctx.fillStyle = vm.backgroundColor;
                        ctx.translate(vm.x, vm.y);
                        ctx.beginPath();
                        ctx.arc(radius * Math.sin(angle), radius * Math.cos(angle), thickness, 0, 2 * Math.PI);
                        ctx.arc(radius * Math.sin(Math.PI), radius * Math.cos(Math.PI), thickness, 0, 2 * Math.PI);
                        ctx.closePath();
                        ctx.fill();
                        ctx.restore();
                    });
                },
            });
    
            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: 'RoundedDoughnut',
                data: deliveredData,
                options: deliveredOpt
            });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.0.1/Chart.bundle.min.js"></script>
    
    <canvas id="openedCanvas" height="230" width="680"></canvas>

    0 讨论(0)
提交回复
热议问题