Javascript ChartJS:将标签放置在甜甜圈段的末尾

Javascript ChartJS:将标签放置在甜甜圈段的末尾,javascript,charts,chart.js,Javascript,Charts,Chart.js,我使用的是带有扩展的chartJS,它基本上是一个定制的甜甜圈,用于创建仪表样式的图表。我已经添加了标签,因此我可以自定义标签 饼图和油炸圈饼图中的标签通常用于显示该段的值,但由于这已自定义为显示为仪表,因此我希望将数据标签放置在每个段的末尾,以便显示该点的值,如下所示: 虽然可以使用“锚定”、“对齐”和“偏移”来移动标签,但它们允许围绕某个点进行有限的移动,我无法找到实现所需的方法。我可以锚定到“end”以使标签位于仪表外部,然后我想也许我可以结合align和offset将标签推到段的末端,

我使用的是带有扩展的chartJS,它基本上是一个定制的甜甜圈,用于创建仪表样式的图表。我已经添加了标签,因此我可以自定义标签

饼图和油炸圈饼图中的标签通常用于显示该段的值,但由于这已自定义为显示为仪表,因此我希望将数据标签放置在每个段的末尾,以便显示该点的值,如下所示:

虽然可以使用“锚定”、“对齐”和“偏移”来移动标签,但它们允许围绕某个点进行有限的移动,我无法找到实现所需的方法。我可以锚定到“end”以使标签位于仪表外部,然后我想也许我可以结合align和offset将标签推到段的末端,但不幸的是,这些命令似乎基于整个仪表的轴而不是弧形段工作

下面是我用来设置选项和数据的代码。这在Salesforce Aura组件中,因此chartJsGaugeInstance从控制器获取值:

let chartJsGaugeInstance = component.get("v.dataInstance");
let type = chartJsGaugeInstance.type;
let target = chartJsGaugeInstance.targetValue;
let firstDivide = target * 0.33;
let secondDivide = target * 0.66;
let data = {
    datasets : [{
        backgroundColor: ["#0fdc63", "#fd9704", "#ff7143"],
        data: [firstDivide, secondDivide, target],
        value: chartJsGaugeInstance.dataValues,
        datalabels: {
            anchor: 'center',
            align: 'center',
            offset: 0
        }
    }]
};

let options = {
    responsive: true,
    title: {
        display: true,
        text: chartJsGaugeInstance.title
    },
    layout: {
        padding: {
            bottom: 30
        }
    },
    needle: {
        // Needle circle radius as the percentage of the chart area width
        radiusPercentage: 1.5,
        // Needle width as the percentage of the chart area width
        widthPercentage: 1,
        // Needle length as the percentage of the interval between inner radius (0%) and outer radius (100%) of the arc
        lengthPercentage: 80,
        // The color of the needle
        color: 'rgba(0, 0, 0, 1)'
    },
    valueLabel: {
        formatter: Math.round
    },
    cutoutPercentage : 80,
    plugins: {
        datalabels: {
            display: true,
            formatter:  function (value, context) {
                return context.chart.data.labels[context.dataIndex];
            },
            color: 'rgba(0, 0, 0, 1.0)',
            backgroundColor: null,
            font: {
                size: 16
            }
        }
    }
}
这是结果图: 我可以通过更改datasets对象中的datalabels参数来移动标签(在本例中,我将它们放在中间),但由于它们都是相对于图表区域移动的,而不是相对于相对线段的方向,因此我无法使它们都对齐到线段的末端。下面是一个示例,它将6k标签移到了正确的位置,但3k和10k标签最终会被移出:

datalabels: {
    anchor: 'end',
    align: 'right',
    offset: 50
}
是我用于数据标签定位的文档。“对齐”部分下的一行表示:

“结束”:标签位于锚定点之后,方向相同

我认为这就是我想要的,“遵循相同的方向”对我来说建议它应该遵循片段的弧线,但它没有:

datalabels: {
    anchor: 'end',
    align: 'end',
    offset: 20
}

还有其他人做到了吗?自2018年起被标记为“增强”,但不知道是否有一种方法可以通过编程或编辑源文件来实现这一点,因为它看起来不会很快交付

谢谢

更新

我已经设法使用可编写脚本的选项找到了部分解决方案。下面对代码的更新为我在每个扇区的末尾提供了位置良好的标签。我已经将datalabels代码从数据集中移到了选项中

let numSectors = data.datasets[0].data.length;
let sectorDegree = 180 / numSectors;

datalabels: {
    anchor: 'end',
    align: function(context){
        return (sectorDegree * context.dataIndex) - sectorDegree;
    },
    offset: function(context){
        return 70;
    },
    ...
}
这导致:


对于我当前的项目,我很满意这一点,因为我总是有三个平均分割的扇区,但这并不是一个完整的解决方案。我计算的角度在很大程度上取决于偏移量。更改偏移意味着对齐计算不再提供良好的结果。这里最大的问题是,由于偏移非常关键,更改扇区数意味着此解决方案不再有效。

您在align函数中的代码确实帮助了我开始使用,但我希望定位有点不同,我编写此代码是为了根据线段数量计算位置,所需的字体大小(适当的偏移量)和画布父级的宽度

让numSectors=在此处插入数据数组的长度;
让sectorDegree=180/numSector;
让width=(canvas.parent().width()-parseInt(canvas.css('padding').replace('px','')*2));
让fontSize=16;
设b=(宽度/2)-3;
设c=b-(fontSize*1.8);
设a=Math.sqrt((Math.pow(b,2)+Math.pow(c,2))-(2*b*c*Math.cos((sectorDegree/2)*Math.PI/180));
设偏移量=a-(fontSize*1.2);

让alignAngle=(Math.asin(Math.sin((sectorDegree/2)*Math.PI/180)*c/a)*180/Math.PI)-(sectorDegree/2)您在align函数中的代码确实帮助了我入门,但我希望定位有点不同,我编写此代码是为了根据段数、所需字体大小(适当偏移)和画布父级的宽度来计算位置

让numSectors=在此处插入数据数组的长度;
让sectorDegree=180/numSector;
让width=(canvas.parent().width()-parseInt(canvas.css('padding').replace('px','')*2));
让fontSize=16;
设b=(宽度/2)-3;
设c=b-(fontSize*1.8);
设a=Math.sqrt((Math.pow(b,2)+Math.pow(c,2))-(2*b*c*Math.cos((sectorDegree/2)*Math.PI/180));
设偏移量=a-(fontSize*1.2);

让alignAngle=(Math.asin(Math.sin((sectorDegree/2)*Math.PI/180)*c/a)*180/Math.PI)-(sectorDegree/2)请发布生成上述图表的代码。这将使你更容易为你的问题提出一个解决方案。虽然插件真的能做这项工作,但我只是设置了一些参数。请发布你的代码,生成上面的图表。这将使你更容易为你的问题提出一个解决方案