Sve*_*erg 13 javascript charts chart.js
chart.js 2.6.0
我需要渲染一个如下所示的图表:
始终显示所有工具提示是不可接受的方式,因为它们不会以适当的方式呈现:
不幸的是我找不到解决方案了.我已经尝试了片标签插件,但这有同样的问题,因为它的标签重叠,我无法隐藏某些标签.
这是代码,它使用piece-label创建我的图表以将标签定位在切片上方:
private createStatusChart(): void {
const chartData = this.getStatusChartData();
if (!chartData) {
return;
}
const $container = $(Templates.Dashboard.ChartContainer({
ContainerID: 'chart-status',
HeaderText: 'Status'
}));
this._$content.append($container);
const legendOptions =
new Model.Charts.LegendOptions()
.SetDisplay(false);
const pieceLabelOptions =
new Model.Charts.PieceLabelOptions()
.SetRender('label')
.SetPosition('outside')
.SetArc(true)
.SetOverlap(true);
const options =
new Model.Charts.Options()
.SetLegend(legendOptions)
.SetPieceLabel(pieceLabelOptions);
const chartDefinition = new Model.Charts.Pie(chartData, options);
const ctx = this._$content.find('#chart-status canvas').get(0);
const chart = new Chart(ctx, chartDefinition);
}
private getStatusChartData(): Model.Charts.PieChartData {
if (!this._data) {
return;
}
const instance = this;
const data: Array<number> = [];
const labels: Array<string> = [];
const colors: Array<string> = [];
this._data.StatusGroupings.forEach(sg => {
if (!sg.StatusOID) {
data.push(sg.Count);
labels.push(i18next.t('Dashboard.NoStateSet'));
colors.push('#4572A7');
return;
}
const status = DAL.Properties.GetByOID(sg.StatusOID);
data.push(sg.Count);
labels.push(status ? status.Title : i18next.t('Misc.Unknown'));
colors.push(status ? status.Color : '#fff');
});
const dataset = new Model.Charts.Dataset(data).setBackgroundColor(colors);
return new Model.Charts.PieChartData(labels, [dataset]);
}
Run Code Online (Sandbox Code Playgroud)
结果:
小智 9
有一个新插件(从一年开始),叫做chartjs-plugin-piechart-outlabels
只需导入源
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-piechart-outlabels"></script>
并将其与 outlabeledPie 类型一起使用
var randomScalingFactor = function() {
return Math.round(Math.random() * 100);
};
var ctx = document.getElementById("chart-area").getContext("2d");
var myDoughnut = new Chart(ctx, {
type: 'outlabeledPie',
data: {
labels: ["January", "February", "March", "April", "May"],
...
plugins: {
legend: false,
outlabels: {
text: '%l %p',
color: 'white',
stretch: 45,
font: {
resizable: true,
minSize: 12,
maxSize: 18
}
}
}
})
Run Code Online (Sandbox Code Playgroud)
我找不到确切的插件,但我制作了一个。
const data = {
labels: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
datasets: [
{
data: [1, 2, 3, 4, 5, 6],
backgroundColor: [
"#316065",
"#1A7F89",
"#2D9CA7",
"#2D86A7",
"#1167A7",
"#142440",
],
borderColor: [
"#316065",
"#1A7F89",
"#2D9CA7",
"#2D86A7",
"#1167A7",
"#142440",
],
},
],
};
// pieLabelsLine plugin
const pieLabelsLine = {
id: "pieLabelsLine",
afterDraw(chart) {
const {
ctx,
chartArea: { width, height },
} = chart;
const cx = chart._metasets[0].data[0].x;
const cy = chart._metasets[0].data[0].y;
const sum = chart.data.datasets[0].data.reduce((a, b) => a + b, 0);
chart.data.datasets.forEach((dataset, i) => {
chart.getDatasetMeta(i).data.forEach((datapoint, index) => {
const { x: a, y: b } = datapoint.tooltipPosition();
const x = 2 * a - cx;
const y = 2 * b - cy;
// draw line
const halfwidth = width / 2;
const halfheight = height / 2;
const xLine = x >= halfwidth ? x + 20 : x - 20;
const yLine = y >= halfheight ? y + 20 : y - 20;
const extraLine = x >= halfwidth ? 10 : -10;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.arc(x, y, 2, 0, 2 * Math.PI, true);
ctx.fill();
ctx.moveTo(x, y);
ctx.lineTo(xLine, yLine);
ctx.lineTo(xLine + extraLine, yLine);
// ctx.strokeStyle = dataset.backgroundColor[index];
ctx.strokeStyle = "black";
ctx.stroke();
// text
const textWidth = ctx.measureText(chart.data.labels[index]).width;
ctx.font = "12px Arial";
// control the position
const textXPosition = x >= halfwidth ? "left" : "right";
const plusFivePx = x >= halfwidth ? 5 : -5;
ctx.textAlign = textXPosition;
ctx.textBaseline = "middle";
// ctx.fillStyle = dataset.backgroundColor[index];
ctx.fillStyle = "black";
ctx.fillText(
((chart.data.datasets[0].data[index] * 100) / sum).toFixed(2) +
"%",
xLine + extraLine + plusFivePx,
yLine
);
});
});
},
};
// config
const config = {
type: "pie",
data,
options: {
maintainAspectRatio: false,
layout: {
padding: 30,
},
scales: {
y: {
display: false,
beginAtZero: true,
ticks: {
display: false,
},
grid: {
display: false,
},
},
x: {
display: false,
ticks: {
display: false,
},
grid: {
display: false,
},
},
},
plugins: {
legend: {
display: false,
},
},
},
plugins: [pieLabelsLine],
};
// render init block
const myChart = new Chart(document.getElementById("myChart"), config);
Run Code Online (Sandbox Code Playgroud)
https://codepen.io/BillDou/pen/oNoGBXb
真正的问题在于切片很小时标签的重叠。您可以使用PieceLabel.js,它通过隐藏标签来解决重叠标签的问题。您提到您无法隐藏标签,因此请使用图例,它将显示所有切片的名称
或者,如果您想要精确的行为,您可以使用 highcharts ,但它需要商业使用许可。
var randomScalingFactor = function() {
return Math.round(Math.random() * 100);
};
var ctx = document.getElementById("chart-area").getContext("2d");
var myDoughnut = new Chart(ctx, {
type: 'pie',
data: {
labels: ["January", "February", "March", "April", "May"],
datasets: [{
data: [
250,
30,
5,
4,
2,
],
backgroundColor: ['#ff3d67', '#ff9f40', '#ffcd56', '#4bc0c0', '#999999'],
borderColor: 'white',
borderWidth: 5,
}]
},
showDatapoints: true,
options: {
tooltips: {
enabled: false
},
pieceLabel: {
render: 'label',
arc: true,
fontColor: '#000',
position: 'outside'
},
responsive: true,
legend: {
position: 'top',
},
title: {
display: true,
text: 'Testing',
fontSize: 20
},
animation: {
animateScale: true,
animateRotate: true
}
}
});Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script>
<script src="https://cdn.rawgit.com/emn178/Chart.PieceLabel.js/master/build/Chart.PieceLabel.min.js"></script>
<canvas id="chart-area"></canvas>Run Code Online (Sandbox Code Playgroud)
小提琴演示