Chart JS 甜甜圈,在一个方向上有圆角边缘,各段之间有白色边框

问题描述 投票:0回答:1

Chart js Donut 段不向一个方向显示。第一个和最后一个片段未按预期工作在此处输入图像描述

期望:需要图表 js 甜甜圈圆形段显示在一个方向上,段之间有白色边框 在此输入图片描述

代码

// Create a custom Doughnut type with rounded segments
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;
    var borderWidth = 20; // Width of the white border for space between segments
    Chart.helpers.each(arcs, function(arc, i) {
      var vm = arc._view;
      var startAngle = vm.startAngle;
      var endAngle = vm.endAngle;
      var radius = (vm.outerRadius + vm.innerRadius) / 2;
      var thickness = (vm.outerRadius - vm.innerRadius) / 2;
      ctx.save();
      ctx.translate(vm.x, vm.y);
      // Draw each arc segment with a white border to create spacing
      ctx.beginPath();
      ctx.arc(0, 0, radius, startAngle, endAngle);
      ctx.lineWidth = thickness * 2 + borderWidth; // Increase width to add border
      ctx.strokeStyle = '#FFFFFF'; // Set border color to white
      ctx.lineCap = 'round'; // Ensure all segments are rounded on both ends
      ctx.stroke();
      // Draw inner colored arc over the white border to make it look like a gap
      ctx.beginPath();
      ctx.arc(0, 0, radius, startAngle, endAngle);
      ctx.lineWidth = thickness * 2;
      ctx.strokeStyle = vm.backgroundColor; // Set segment color
      ctx.stroke();

      ctx.restore();
    });
  }
});
// Initialize the chart
window.onload = function() {
  new Chart(document.getElementById('usersChart'), {
    type: 'RoundedDoughnut',
    data: {
      datasets: [{
        data: [10, 10, 10, 10, 10, 10, 10, 10], // Adjust data values for even segments
        backgroundColor: [
          '#5da4e7', '#8fbbe7', '#addbf0', '#4b8de7',
          '#4da466', '#8ec486', '#b3dba8', '#63b571'
        ],
        borderWidth: 0
      }]
    },
    options: {
      cutoutPercentage: 70,
      tooltips: {
        enabled: false
      } // Optional: Disable tooltips to prevent hover issues
    }
  });
};
<canvas id="usersChart" width="400" height="400"></canvas>

javascript jquery chart.js donut-chart
1个回答
0
投票

您应该指定您正在使用的chart.js版本,以防它不是 最新的,但似乎不是,因为您的代码 自定义控制器与最新 v4 版本的 Chart.js 不兼容。

无论如何,问题是概念性的,即圆形“甲板”的想法 卡”,每张卡都被下一张卡部分覆盖,无法实现 通过抽整张牌,因为这种方法必然有一张牌 完全可见,一张卡两端都被覆盖。

另一种选择是抽半张牌,这会起作用,除了在 当扇区的大小非常小时的情况 - 那么可见 半扇区太多,扇区会错误重叠。

最好的解决方案似乎是实际绘制重叠部分,使用

context.fill
函数,填充半圆,而不是
context.stroke
非常粗的弧线,末端呈圆形。

这是该想法的实现,使用最新的 Chart.js v4 兼容 控制器;应该很容易使其适应旧版本:

class RoundedDoughnut extends Chart.controllers.doughnut {
    static id = "roundedDoughnut";
    draw(...args) {
        super.draw(...args);

        const ctx = this.chart.ctx;
        const arcs = this.getMeta().data;
        const borderWidth = 10;
        const borderColor = 'white';

        if(arcs.length === 0){
            return;
        }

        ctx.save();

        const arc = arcs[0];
        ctx.strokeStyle = borderColor;
        ctx.lineWidth = borderWidth;
        ctx.beginPath();
        ctx.arc(arc.x, arc.y, arc.innerRadius, 0, 2*Math.PI);
        ctx.stroke();
        ctx.beginPath();
        ctx.arc(arc.x, arc.y, arc.outerRadius, 0, 2*Math.PI);
        ctx.stroke();

        for(const arc of arcs){
            const startAngle = arc.startAngle,
                radius = (arc.outerRadius + arc.innerRadius) / 2,
                thickness = (arc.outerRadius - arc.innerRadius) / 2 - borderWidth;
            const x0 = arc.x + radius * Math.cos(startAngle),
                y0 = arc.y + radius * Math.sin(startAngle);
            ctx.beginPath();
            ctx.arc(x0, y0, thickness, Math.PI + startAngle, 2*Math.PI + startAngle);
            ctx.lineTo(x0 - thickness * Math.cos(startAngle), y0 - thickness * Math.sin(startAngle));
            ctx.fillStyle = arc.options.backgroundColor;
            ctx.strokeStyle = arc.options.backgroundColor;
            ctx.lineWidth = borderWidth;
            ctx.fill();
            ctx.stroke();

            ctx.beginPath();
            ctx.arc(x0, y0, thickness + borderWidth, Math.PI + startAngle, 2*Math.PI + startAngle);
            ctx.strokeStyle = borderColor;
            ctx.stroke();
        }
        ctx.restore();

    }
}

Chart.registry.controllers.register(RoundedDoughnut)

new Chart(document.getElementById('usersChart'), {
    type: 'roundedDoughnut',
    data: {
        datasets: [{
            data: [10, 10, 10, 10, 10, 10, 10, 10], // Adjust data values for even segments
            backgroundColor: [
                '#5da4e7', '#8fbbe7', '#addbf0', '#4b8de7',
                '#4da466', '#8ec486', '#b3dba8', '#63b571'
            ],
            borderWidth: 0
        }]
    },
    options: {
        cutoutPercentage: 70,
        layout:{
            padding: 10
        },
        tooltips: {
            enabled: false
        } // Optional: Disable tooltips to prevent hover issues
    }
});
<div style="width:400px; height: 400px">
<canvas id="usersChart"></canvas>
</div>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

© www.soinside.com 2019 - 2024. All rights reserved.