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>
您应该指定您正在使用的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>