【问题标题】:Chart.js Doughnut with rounded edgesChart.js 圆角甜甜圈
【发布时间】:2016-08-24 09:59:00
【问题描述】:

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

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

我找到的最好的答案是:How to put rounded corners on a Chart.js Bar chart,但它适用于条形图,我不知道如何将其用于甜甜圈。

这是我的代码:

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
    });
}};

有人知道怎么做吗?

【问题讨论】:

    标签: javascript canvas charts chart.js


    【解决方案1】:

    你可以扩展图表来做到这一点


    预览


    脚本

    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();
            });
        },
    });
    

    然后

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

    堆栈片段

    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>

    【讨论】:

    • 事实上,当 value = 0 时,图的顶部有一个绿球,但它应该什么也不显示。我用一个声明解决了这个问题,如果 value == 0,则使用“doughnut”,否则使用“RoundedDoughnut”。再次,非常感谢!
    • 啊,我没想到 0。干杯!
    • 这很棒。对于更多数据集,我需要这样的效果。让我们以他们在文档页面上使用的 [300, 50, 100] 为例。我得到类似take.ms/JRqgh 的东西,知道@potatopeelings 如何实现吗?我的目标是这样的take.ms/thRIb
    • 这个解决方案是否仍然适用于当前版本的 chart.js?
    • @GabrielBueno @jaminroe 要让它在当前版本的 chart.js 中工作:将 this.getDataset().metaData 替换为 this.getMeta().data
    【解决方案2】:

    我在@potatopeeling sn-p 中做了一些更改,我与更新的 (2.9.x) 版本的 chart.js 兼容,还修复了应该呈现“startArc”的位置以及前一段的颜色以匹配这个“startArc”,所以我们可以有两个以上的段。结果如下:

    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 的图表上。除此之外,干得好!
    • 我想根据数据集的值进行绘图。比如绿色粉色和蓝色各有 2 个。只希望这样。而不是紫色。使用 abv 代码,我将蓝色变为一个点。
    • 如何在每一个之间添加间距?
    • 我们可以用什么方法让这个工作也与borderWidth一起工作?
    • @AFriend 只需将 Chart.helpers.each(arcs, function(arc, i) { 替换为 Chart.helpers.each(arcs.filter(item =&gt; item.$context.parsed &gt; 0), function(arc, i) { 即可不为 0 数据渲染颜色
    猜你喜欢
    • 1970-01-01
    • 2016-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-11
    • 1970-01-01
    相关资源
    最近更新 更多