Chart.js (v3) 带圆边的甜甜圈,但不是到处都是
Chart.js (v3) Doughnut with rounded edges, but not everywhere
我知道对此有几个答案,但这个似乎有点不同。我需要更改甜甜圈图,将第一个和最后一个也四舍五入。因此,在我的示例中,黑色(第一个数据集)只会在开头(一侧)四舍五入,而灰色(最后一个数据集)会在最后四舍五入,如图所示。
当然,这是Chart.js的最新版本(v3)。
我使用了这里的一些代码:
也许使用自定义图表会更好,但我什至无法做到这一点。
到目前为止,这是我的代码。只使第一个数据集四舍五入,不幸的是它的两边。
Chart.defaults.elements.arc.borderWidth = 0;
Chart.defaults.elements.arc.roundedCornersFor = 0;
Chart.defaults.elements.arc.hoverBorderColor = 'white';
Chart.defaults.datasets.doughnut.cutout = '85%';
var doughnutChart = document.getElementById('doughnutChart');
if(doughnutChart) {
new Chart(doughnutChart, {
type: 'doughnut',
// The data for our dataset
data: {
labels: [
'Label 1',
'Label 2',
'Label 3',
'Label 4'
],
datasets: [{
label: 'My First Dataset',
data: [22, 31, 26, 19],
backgroundColor: [
'#000000',
'#ffff00',
'#aaaaaa',
'#ff0000'
]
}]
},
plugins: [
{
afterUpdate: function(chart) {
if (chart.options.elements.arc.roundedCornersFor !== undefined) {
var arc = chart.getDatasetMeta(0).data[chart.options.elements.arc.roundedCornersFor];
arc.round = {
x: (chart.chartArea.left + chart.chartArea.right) / 2,
y: (chart.chartArea.top + chart.chartArea.bottom) / 2,
radius: (arc.outerRadius + arc.innerRadius) / 2,
thickness: (arc.outerRadius - arc.innerRadius) / 2,
backgroundColor: arc.options.backgroundColor
}
}
},
afterDraw: (chart) => {
if (chart.options.elements.arc.roundedCornersFor !== undefined) {
var {ctx, canvas} = chart;
var arc = chart.getDatasetMeta(0).data[chart.options.elements.arc.roundedCornersFor];
var startAngle = Math.PI / 2 - arc.startAngle;
var endAngle = Math.PI / 2 - arc.endAngle;
ctx.save();
ctx.translate(arc.round.x, arc.round.y);
ctx.fillStyle = arc.round.backgroundColor;
ctx.beginPath();
ctx.arc(arc.round.radius * Math.sin(startAngle), arc.round.radius * Math.cos(startAngle), arc.round.thickness, 0, 2 * Math.PI);
ctx.arc(arc.round.radius * Math.sin(endAngle), arc.round.radius * Math.cos(endAngle), arc.round.thickness, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
ctx.restore();
}
}
}
]
});
}
.container {
width: 400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.min.js"></script>
<div class="container">
<canvas id="doughnutChart"></canvas>
</div>
我已经修改了您的代码并针对 roundedCornersFor
进行了更改。它现在将采用一个对象结构,该结构将定义以 start
和 end
作为键,值将是根据标签的弧位置。
Chart.defaults.elements.arc.roundedCornersFor = {
"start": 0, //0th position of Label 1
"end": 2 //2nd position of Label 2
};
下面是完整的代码片段:
Chart.defaults.elements.arc.borderWidth = 0;
Chart.defaults.elements.arc.roundedCornersFor = {
"start": 0, //0th position of Label 1
"end": 2 //2nd position of Label 2
};
//Can be provided as array:
//Chart.defaults.elements.arc.roundedCornersFor = {
// "start": [0,1,2],
// "end": 3
//};
Chart.defaults.elements.arc.hoverBorderColor = 'white';
Chart.defaults.datasets.doughnut.cutout = '85%';
var chartInstance = new Chart(document.getElementById("chartJSContainer"), {
type: 'doughnut',
// The data for our dataset
data: {
labels: [
'Label 1',
'Label 2',
'Label 3',
'Label 4'
],
datasets: [{
label: 'My First Dataset',
data: [22, 31, 26, 19],
backgroundColor: [
'#000000',
'#ffff00',
'#aaaaaa',
'#ff0000'
]
}]
},
//Inline Options...
/* options: {
elements: {
arc: {
roundedCornersFor: {
"start": 1, //0th position of Label 1
"end": 1 //2nd position of Label 2
}
}
}
}, */
plugins: [{
afterUpdate: function(chart) {
if (chart.options.elements.arc.roundedCornersFor !== undefined) {
var arcValues = Object.values(chart.options.elements.arc.roundedCornersFor);
arcValues.forEach(function(arcs) {
arcs = Array.isArray(arcs) ? arcs : [arcs];
arcs.forEach(function(i) {
var arc = chart.getDatasetMeta(0).data[i];
arc.round = {
x: (chart.chartArea.left + chart.chartArea.right) / 2,
y: (chart.chartArea.top + chart.chartArea.bottom) / 2,
radius: (arc.outerRadius + arc.innerRadius) / 2,
thickness: (arc.outerRadius - arc.innerRadius) / 2,
backgroundColor: arc.options.backgroundColor
}
});
});
}
},
afterDraw: (chart) => {
if (chart.options.elements.arc.roundedCornersFor !== undefined) {
var {
ctx,
canvas
} = chart;
var arc,
roundedCornersFor = chart.options.elements.arc.roundedCornersFor;
for (var position in roundedCornersFor) {
var values = Array.isArray(roundedCornersFor[position]) ? roundedCornersFor[position] : [roundedCornersFor[position]];
values.forEach(p => {
arc = chart.getDatasetMeta(0).data[p];
var startAngle = Math.PI / 2 - arc.startAngle;
var endAngle = Math.PI / 2 - arc.endAngle;
ctx.save();
ctx.translate(arc.round.x, arc.round.y);
ctx.fillStyle = arc.options.backgroundColor;
ctx.beginPath();
if (position == "start") {
ctx.arc(arc.round.radius * Math.sin(startAngle), arc.round.radius * Math.cos(startAngle), arc.round.thickness, 0, 2 * Math.PI);
} else {
ctx.arc(arc.round.radius * Math.sin(endAngle), arc.round.radius * Math.cos(endAngle), arc.round.thickness, 0, 2 * Math.PI);
}
ctx.closePath();
ctx.fill();
ctx.restore();
});
};
}
}
}]
});
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.3.1/dist/chart.js"></script>
<body>
<canvas id="chartJSContainer" width="200" height="200"></canvas>
</body>
我知道对此有几个答案,但这个似乎有点不同。我需要更改甜甜圈图,将第一个和最后一个也四舍五入。因此,在我的示例中,黑色(第一个数据集)只会在开头(一侧)四舍五入,而灰色(最后一个数据集)会在最后四舍五入,如图所示。
当然,这是Chart.js的最新版本(v3)。
我使用了这里的一些代码:
也许使用自定义图表会更好,但我什至无法做到这一点。
到目前为止,这是我的代码。只使第一个数据集四舍五入,不幸的是它的两边。
Chart.defaults.elements.arc.borderWidth = 0;
Chart.defaults.elements.arc.roundedCornersFor = 0;
Chart.defaults.elements.arc.hoverBorderColor = 'white';
Chart.defaults.datasets.doughnut.cutout = '85%';
var doughnutChart = document.getElementById('doughnutChart');
if(doughnutChart) {
new Chart(doughnutChart, {
type: 'doughnut',
// The data for our dataset
data: {
labels: [
'Label 1',
'Label 2',
'Label 3',
'Label 4'
],
datasets: [{
label: 'My First Dataset',
data: [22, 31, 26, 19],
backgroundColor: [
'#000000',
'#ffff00',
'#aaaaaa',
'#ff0000'
]
}]
},
plugins: [
{
afterUpdate: function(chart) {
if (chart.options.elements.arc.roundedCornersFor !== undefined) {
var arc = chart.getDatasetMeta(0).data[chart.options.elements.arc.roundedCornersFor];
arc.round = {
x: (chart.chartArea.left + chart.chartArea.right) / 2,
y: (chart.chartArea.top + chart.chartArea.bottom) / 2,
radius: (arc.outerRadius + arc.innerRadius) / 2,
thickness: (arc.outerRadius - arc.innerRadius) / 2,
backgroundColor: arc.options.backgroundColor
}
}
},
afterDraw: (chart) => {
if (chart.options.elements.arc.roundedCornersFor !== undefined) {
var {ctx, canvas} = chart;
var arc = chart.getDatasetMeta(0).data[chart.options.elements.arc.roundedCornersFor];
var startAngle = Math.PI / 2 - arc.startAngle;
var endAngle = Math.PI / 2 - arc.endAngle;
ctx.save();
ctx.translate(arc.round.x, arc.round.y);
ctx.fillStyle = arc.round.backgroundColor;
ctx.beginPath();
ctx.arc(arc.round.radius * Math.sin(startAngle), arc.round.radius * Math.cos(startAngle), arc.round.thickness, 0, 2 * Math.PI);
ctx.arc(arc.round.radius * Math.sin(endAngle), arc.round.radius * Math.cos(endAngle), arc.round.thickness, 0, 2 * Math.PI);
ctx.closePath();
ctx.fill();
ctx.restore();
}
}
}
]
});
}
.container {
width: 400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.min.js"></script>
<div class="container">
<canvas id="doughnutChart"></canvas>
</div>
我已经修改了您的代码并针对 roundedCornersFor
进行了更改。它现在将采用一个对象结构,该结构将定义以 start
和 end
作为键,值将是根据标签的弧位置。
Chart.defaults.elements.arc.roundedCornersFor = {
"start": 0, //0th position of Label 1
"end": 2 //2nd position of Label 2
};
下面是完整的代码片段:
Chart.defaults.elements.arc.borderWidth = 0;
Chart.defaults.elements.arc.roundedCornersFor = {
"start": 0, //0th position of Label 1
"end": 2 //2nd position of Label 2
};
//Can be provided as array:
//Chart.defaults.elements.arc.roundedCornersFor = {
// "start": [0,1,2],
// "end": 3
//};
Chart.defaults.elements.arc.hoverBorderColor = 'white';
Chart.defaults.datasets.doughnut.cutout = '85%';
var chartInstance = new Chart(document.getElementById("chartJSContainer"), {
type: 'doughnut',
// The data for our dataset
data: {
labels: [
'Label 1',
'Label 2',
'Label 3',
'Label 4'
],
datasets: [{
label: 'My First Dataset',
data: [22, 31, 26, 19],
backgroundColor: [
'#000000',
'#ffff00',
'#aaaaaa',
'#ff0000'
]
}]
},
//Inline Options...
/* options: {
elements: {
arc: {
roundedCornersFor: {
"start": 1, //0th position of Label 1
"end": 1 //2nd position of Label 2
}
}
}
}, */
plugins: [{
afterUpdate: function(chart) {
if (chart.options.elements.arc.roundedCornersFor !== undefined) {
var arcValues = Object.values(chart.options.elements.arc.roundedCornersFor);
arcValues.forEach(function(arcs) {
arcs = Array.isArray(arcs) ? arcs : [arcs];
arcs.forEach(function(i) {
var arc = chart.getDatasetMeta(0).data[i];
arc.round = {
x: (chart.chartArea.left + chart.chartArea.right) / 2,
y: (chart.chartArea.top + chart.chartArea.bottom) / 2,
radius: (arc.outerRadius + arc.innerRadius) / 2,
thickness: (arc.outerRadius - arc.innerRadius) / 2,
backgroundColor: arc.options.backgroundColor
}
});
});
}
},
afterDraw: (chart) => {
if (chart.options.elements.arc.roundedCornersFor !== undefined) {
var {
ctx,
canvas
} = chart;
var arc,
roundedCornersFor = chart.options.elements.arc.roundedCornersFor;
for (var position in roundedCornersFor) {
var values = Array.isArray(roundedCornersFor[position]) ? roundedCornersFor[position] : [roundedCornersFor[position]];
values.forEach(p => {
arc = chart.getDatasetMeta(0).data[p];
var startAngle = Math.PI / 2 - arc.startAngle;
var endAngle = Math.PI / 2 - arc.endAngle;
ctx.save();
ctx.translate(arc.round.x, arc.round.y);
ctx.fillStyle = arc.options.backgroundColor;
ctx.beginPath();
if (position == "start") {
ctx.arc(arc.round.radius * Math.sin(startAngle), arc.round.radius * Math.cos(startAngle), arc.round.thickness, 0, 2 * Math.PI);
} else {
ctx.arc(arc.round.radius * Math.sin(endAngle), arc.round.radius * Math.cos(endAngle), arc.round.thickness, 0, 2 * Math.PI);
}
ctx.closePath();
ctx.fill();
ctx.restore();
});
};
}
}
}]
});
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.3.1/dist/chart.js"></script>
<body>
<canvas id="chartJSContainer" width="200" height="200"></canvas>
</body>