Chart.js v2: space between doughnut inside doughnut

前端 未结 4 1485
眼角桃花
眼角桃花 2021-01-22 20:29

I am using chart.js v2.5.0. I put doughnut inside doughnut.

I want the disdance between 2 doughnuts(A) to be larger without affecting the distance betwe

相关标签:
4条回答
  • 2021-01-22 20:50

    Another solution here : 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>

    0 讨论(0)
  • 2021-01-22 21:04

    The only way to achieve this is to extend the existing doughnut controller and overwrite the update method with your own logic for determining the spacing.

    Here is an example demonstrating how you would do this. With this implementation, I added a new doughnut chart option property called datasetRadiusBuffer that controls the white space between each dataset.

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

    You can see a live example at this codepen.

    0 讨论(0)
  • 2021-01-22 21:05

    To make it work with the latest ChartJS 2.7.2, I've just copied the source as suggested from https://github.com/chartjs/Chart.js/blob/master/src/controllers/controller.doughnut.js. Then I added the patch:

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

    Everything was working as expected.

    0 讨论(0)
  • 2021-01-22 21:05

    Picture of 3 datasets in doughnut chart with "padding"

    I achieved this by inserting a transparent dataset between the colored datasets. Didn't find another "easy" way.

    In the end it was easier to do the whole chart myself instead of using chartjs.

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