【问题标题】:Chart.js v2: space between doughnut inside doughnutChart.js v2:甜甜圈内甜甜圈之间的空间
【发布时间】:2017-04-04 08:43:28
【问题描述】:

我正在使用 chart.js v2.5.0。 我把甜甜圈放在甜甜圈里。

我希望 2 个甜甜圈 (A) 之间的距离更大,而不会影响同一个甜甜圈 (B) 内切片之间的距离。

请看下图:

目前我正在使用属性 borderWidth。 但是,这也会影响 B 的宽度。

请看以下代码:

options: {
                elements: {
                    arc: {
                        borderWidth: 18,
                    },
                },
                cutoutPercentage: 60,
                responsive: true,
            }

我希望甜甜圈看起来像这样:

【问题讨论】:

    标签: javascript html css chart.js2


    【解决方案1】:

    实现这一点的唯一方法是扩展现有的doughnut 控制器并用您自己的确定间距的逻辑覆盖update 方法。

    这是一个示例,展示了您将如何执行此操作。通过这个实现,我添加了一个名为datasetRadiusBuffer 的新圆环图选项属性,用于控制每个数据集之间的空白。

    var helpers = Chart.helpers;
    
    // this option will control the white space between embedded charts when there is more than 1 dataset
    helpers.extend(Chart.defaults.doughnut, {
      datasetRadiusBuffer: 0
    });
    
    Chart.controllers.doughnut = Chart.controllers.doughnut.extend({
      update: function(reset) {
        var me = this;
        var chart = me.chart,
            chartArea = chart.chartArea,
            opts = chart.options,
            arcOpts = opts.elements.arc,
            availableWidth = chartArea.right - chartArea.left - arcOpts.borderWidth,
            availableHeight = chartArea.bottom - chartArea.top - arcOpts.borderWidth,
            minSize = Math.min(availableWidth, availableHeight),
            offset = {
              x: 0,
              y: 0
            },
            meta = me.getMeta(),
            cutoutPercentage = opts.cutoutPercentage,
            circumference = opts.circumference;
    
        // If the chart's circumference isn't a full circle, calculate minSize as a ratio of the width/height of the arc
        if (circumference < Math.PI * 2.0) {
          var startAngle = opts.rotation % (Math.PI * 2.0);
          startAngle += Math.PI * 2.0 * (startAngle >= Math.PI ? -1 : startAngle < -Math.PI ? 1 : 0);
          var endAngle = startAngle + circumference;
          var start = {x: Math.cos(startAngle), y: Math.sin(startAngle)};
          var end = {x: Math.cos(endAngle), y: Math.sin(endAngle)};
          var contains0 = (startAngle <= 0 && 0 <= endAngle) || (startAngle <= Math.PI * 2.0 && Math.PI * 2.0 <= endAngle);
          var contains90 = (startAngle <= Math.PI * 0.5 && Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 2.5 && Math.PI * 2.5 <= endAngle);
          var contains180 = (startAngle <= -Math.PI && -Math.PI <= endAngle) || (startAngle <= Math.PI && Math.PI <= endAngle);
          var contains270 = (startAngle <= -Math.PI * 0.5 && -Math.PI * 0.5 <= endAngle) || (startAngle <= Math.PI * 1.5 && Math.PI * 1.5 <= endAngle);
          var cutout = cutoutPercentage / 100.0;
          var min = {x: contains180 ? -1 : Math.min(start.x * (start.x < 0 ? 1 : cutout), end.x * (end.x < 0 ? 1 : cutout)), y: contains270 ? -1 : Math.min(start.y * (start.y < 0 ? 1 : cutout), end.y * (end.y < 0 ? 1 : cutout))};
          var max = {x: contains0 ? 1 : Math.max(start.x * (start.x > 0 ? 1 : cutout), end.x * (end.x > 0 ? 1 : cutout)), y: contains90 ? 1 : Math.max(start.y * (start.y > 0 ? 1 : cutout), end.y * (end.y > 0 ? 1 : cutout))};
          var size = {width: (max.x - min.x) * 0.5, height: (max.y - min.y) * 0.5};
          minSize = Math.min(availableWidth / size.width, availableHeight / size.height);
          offset = {x: (max.x + min.x) * -0.5, y: (max.y + min.y) * -0.5};
        }
    
        chart.borderWidth = me.getMaxBorderWidth(meta.data);
        chart.outerRadius = Math.max((minSize - chart.borderWidth) / 2, 0);
        chart.innerRadius = Math.max(cutoutPercentage ? (chart.outerRadius / 100) * (cutoutPercentage) : 0, 0);
        chart.radiusLength = ((chart.outerRadius - chart.innerRadius) / chart.getVisibleDatasetCount()) + 25;
        chart.offsetX = offset.x * chart.outerRadius;
        chart.offsetY = offset.y * chart.outerRadius;
    
        meta.total = me.calculateTotal();
    
        me.outerRadius = chart.outerRadius - (chart.radiusLength * me.getRingIndex(me.index));
        me.innerRadius = Math.max(me.outerRadius - chart.radiusLength, 0);
    
        // factor in the radius buffer if the chart has more than 1 dataset
        if (me.index > 0) {
          me.outerRadius -= opts.datasetRadiusBuffer;
          me.innerRadius -= opts.datasetRadiusBuffer;
        }
    
        helpers.each(meta.data, function(arc, index) {
          me.updateElement(arc, index, reset);
        });
      },
    });
    

    您可以在codepen 看到一个实时示例。

    【讨论】:

      【解决方案2】:

      为了使它与最新的 ChartJS 2.7.2 一起工作,我刚刚按照https://github.com/chartjs/Chart.js/blob/master/src/controllers/controller.doughnut.js 的建议复制了源代码。然后我添加了补丁:

      if (me.index > 0) {
        me.outerRadius -= opts.datasetRadiusBuffer;
        me.innerRadius -= opts.datasetRadiusBuffer;
      }
      

      一切都按预期进行。

      【讨论】:

        【解决方案3】:

        Picture of 3 datasets in doughnut chart with "padding"

        我通过在彩色数据集之间插入一个透明数据集来实现这一点。没有找到另一种“简单”的方法。

        最后自己做整个图表而不是使用chartjs更容易。

        【讨论】:

          【解决方案4】:

          这里的另一个解决方案:Padding Between Pie Charts in chart js

          const colors = ["#FF6384", "#36A2EB", "#FFCE56"];
          var pieChart = new Chart("myChart", {
               type: 'pie',
               data: {
                     labels: ["Red", "Blue", "Yellow"],
                    datasets: [{      
                             data: [8, 5, 6],
                             backgroundColor: colors,
               },{ 
               weight: 0.2
               },{ 
               data: [5, 7, 4],
               backgroundColor: colors,
               weight: 1.2
               }]
              }
            })
          <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
          <canvas id="myChart"></canvas>

          【讨论】:

            猜你喜欢
            • 2016-08-24
            • 1970-01-01
            • 2016-09-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多