javascript 如何在chart.js中制作圆环图中的圆段分隔符

oxf4rvwz  于 2023-05-05  发布在  Java
关注(0)|答案(1)|浏览(144)

我试着让

看起来像svg,而不使用svg。bcz在angular中,我没有找到任何甜甜圈图表,看起来像

,我确实找到了一个图表,但那是在jquery中,我不能使用jquery。我如何使这个多级圆环图的分段分隔符的边缘变圆我在angular中使用chart.js 4。
下面是一个例子。

var config: any= {
      type: 'doughnut',
      data: {
        
          datasets: [{
            label: 'Dataset 1',
              data: [
                
                {
                  value: 50,                 
              },
              {
                  value: 50,                 
              }
                  
              ],
                  backgroundColor: [
                  "#ff3333",
                  "#660000",                
              ],
                  hoverBackgroundColor: [
                "#ff3333",
                "#660000",
              ],
              hoverBackground: NONE_TYPE,
              borderColor:NONE_TYPE,
              hoverBorderColor:NONE_TYPE,
              borderWidth: 0,
              datalabels : {
                display: false
               }
             
          }, {
            label: 'Dataset 2',
              data: [
                {
                  value: 70,                  
              },
              {
                  value: 30,
              }
              ],
                  backgroundColor: [
                  "#00ff00",
                  "#003300",
               ],
                hoverBackgroundColor: [
                "#00ff00",
                "#003300",
             ],
              
               borderColor:NONE_TYPE,
               hoverBorderColor:NONE_TYPE,
               borderWidth: 0,
               datalabels : {
                display: false
               }
               
          }, {
            label: 'Dataset 3', 
              data: [
                {
                 value:40,                    
              },
              {
                value:60,                  
              }
              
               ],
               labels: [
                'green',
                'yellow',
              ] ,
               backgroundColor: [
                  "#1991EB",
                  "#001f4d",
               ],
               hoverBackgroundColor: [
                "#1991EB",
                  "#001a4d",
              ],
              
               borderColor:NONE_TYPE,
               hoverBorderColor:NONE_TYPE,
               borderWidth: 0,
               datalabels : {
                display: false
               },
               
               
          }], 
        
          
      },
      options: {
          responsive: true,
          legend: {
            display: false
          },           
                
        
      }
  };
o75abkj4

o75abkj41#

圆环图或饼图中圆弧的圆端由borderRadius选项覆盖。
如果我们选择圆端的半径为15 px,我们可以写为

datasets: [{
        //..... data and other dataset options
        borderRadius: [
            {outerStart: 0, outerEnd: 15, innerStart: 0, innerEnd: 15},
            0
        ]
    }]

显然,要舍入另一端,应该设置outerStartinnerStart值。borderRadius数组的第二个值(零)对应于数据集的第二个值,它代表条带的背景。
这里有一段你的数据

const data = {
    datasets: [{
        label: 'Dataset 1',
        data: [50, 50],
        backgroundColor: [
            "#ff3333",
            "#660000",
        ],
        borderRadius: [
            {outerStart: 0, outerEnd: 15, innerStart: 0, innerEnd: 15},
            0
        ],
        borderWidth: 0
    },
    {
        label: 'Dataset 2',
        data: [70, 30],
        backgroundColor: [
            "#00ff00",
            "#003300",
        ],
        borderRadius: [
            {outerStart: 0, outerEnd: 15, innerStart: 0, innerEnd: 15},
            0
        ],
        borderWidth: 0
    },
    {
        label: 'Dataset 3',
        data: [40, 60],
        backgroundColor: [
            "#1991EB",
            "#001a4d",
        ],
        borderRadius: [
            {outerStart: 0, outerEnd: 15, innerStart: 0, innerEnd: 15},
            0
        ],
        borderWidth: 0,
    }]
};

const chart = new Chart(document.querySelector("#myChart"), {
    type: 'doughnut',
    data,
    options: {
        cutout: 60,
        responsive: true,
        radius: "80%"
    }
});
<div style="max-height:350px">
<canvas id="myChart" style="background-color: #000"></canvas>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.3.0/chart.umd.js"
        integrity="sha512-CMF3tQtjOoOJoOKlsS7/2loJlkyctwzSoDK/S40iAB+MqWSaf50uObGQSk5Ny/gfRhRCjNLvoxuCvdnERU4WGg=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>

这样做有几个问题:

  • 背景不是完美的,在圆形的两端有画布背景,而不是第二种颜色,应该是条纹背景
  • 第二个项目(应该作为背景)也会在悬停时生成工具提示,需要禁用
  • 圆形端部的半径必须被预设,并且画布的大小调整可能达到不适当的值(尽管可以实现更新)。

为了涵盖这些情况,我实现了一个自定义的DoughnutController,参见docs,称为DoughnutWithRoundEnds,id为doughnut_round_ends,它扩展了标准的doughnut,具有三个数据集选项:

  • roundStartroundEnd,(每个值的默认值为true),每个值的布尔值(不需要设置边界半径,它是在绘制时考虑弧的当前大小自动计算的)
  • overallBackgroundColor-条纹的非活动背景色-这将允许仅使用一个值并设置circumference
const _drawArcElement = Chart.ArcElement.prototype.draw;
class DoughnutWithRoundEnds extends Chart.DoughnutController{
    static id = "doughnut_round_ends";

    updateElements(arcs, start, count, mode) {
        super.updateElements(arcs, start, count, mode);
        const dataset = this.getDataset();
        const overallBackgroundColor = dataset.overallBackgroundColor ??
            this.options.overallBackgroundColor;
        let roundEnd = this.getDataset().roundEnd ?? this.options.roundEnd ?? true;
        if(!Array.isArray(roundEnd)){
            roundEnd = Array(arcs.length).fill(roundEnd);
        }
        let roundStart = dataset.roundStart ?? this.options.roundStart ?? true;
        if(!Array.isArray(roundStart)){
            roundStart = Array(arcs.length).fill(roundStart);
        }
        if(overallBackgroundColor && roundEnd.length > 0){
            arcs.forEach((arc, i) => {
                let borderRadius = 0;
                if(roundEnd[i] || roundStart[i]){
                    const r = Math.ceil((arc.outerRadius - arc.innerRadius)/2),
                        rStart = roundStart[i] ? r : 0,
                        rEnd = roundEnd[i] ? r : 0;
                    borderRadius = {
                        outerStart: rStart,
                        outerEnd: rEnd,
                        innerStart: rStart,
                        innerEnd: rEnd
                    };
                }
                if(i === 0 && overallBackgroundColor){
                    arc.draw = function(ctx){
                        const backgroundColor = this.options.backgroundColor,
                            startAngle = this.startAngle,
                            endAngle = this.endAngle;
                        this.options.backgroundColor = overallBackgroundColor;
                        this.options.borderRadius = 0;
                        this.startAngle = 0;
                        this.endAngle = 2*Math.PI;
                        _drawArcElement.call(this, ctx);
                        this.options.backgroundColor = backgroundColor;
                        this.startAngle = startAngle;
                        this.endAngle = endAngle;
                        this.options.borderRadius = borderRadius;
                        _drawArcElement.call(this, ctx);
                    }
                }
                else{
                    this.options.borderRadius = borderRadius;
                }
            });
        }
    }
}

Chart.register(DoughnutWithRoundEnds);

const data = {
    datasets: [{
        label: 'Dataset 1',
        data: [50],
        circumference: [50/100*360],
        backgroundColor: [
            "#ff3333"
        ],
        //roundStart: [true], //default
        // roundEnd: [true], // default
        overallBackgroundColor: "#660000",
        borderWidth: 0
    },
    {
        label: 'Dataset 2',
        data: [70],
        circumference: [70/100*360],
        backgroundColor: [
            "#00ff00"
        ],
        overallBackgroundColor: "#003300",
        borderWidth: 0
    },
    {
        label: 'Dataset 3',
        data: [40],
        circumference: [40/100*360],
        backgroundColor: [
            "#1991EB",
        ],
        overallBackgroundColor: "#001a4d",
        borderWidth: 0
    }]
};

const chart = new Chart(document.querySelector("#myChart"), {
    type: 'doughnut_round_ends',
    data,
    options: {
        cutout: 60,
        responsive: true,
        radius: "80%",
        //roundStart: false // for all datasets
    }
});
<div style="max-height:350px">
<canvas id="myChart" style="background-color: #000"></canvas>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.3.0/chart.umd.js"
        integrity="sha512-CMF3tQtjOoOJoOKlsS7/2loJlkyctwzSoDK/S40iAB+MqWSaf50uObGQSk5Ny/gfRhRCjNLvoxuCvdnERU4WGg=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>

这个版本也适用于两个(或更多)值,就像第一种情况一样,如果第二个值是相关的,而不仅仅是背景:jsFiddle

相关问题