10👍
There is a new plugin (since a year),
called chartjs-plugin-piechart-outlabels
Just import the source
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-piechart-outlabels"></script>
and use it with the outlabeledPie type
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
}
}
}
})
5👍
I can’t find an exact plugin but I make one.
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);
2👍
The real problem lies with the overlapping of the labels when the slices are small.You can use PieceLabel.js which solves the issue of overlapping labels by hiding it . You mentioned that you cannot hide labels so use legends, which will display names of all slices
Or if you want exact behavior you can go with the highcharts, but it requires licence for commercial use.
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
}
}
});
<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>
Fiddle demo
1👍
I resolved:
We add script to file global:
if(window.Chartist && Chartist.Pie && !Chartist.Pie.prototype.resolveOverlap) {
Chartist.Pie.prototype.resolveOverlap = function() {
this.on('draw', function(ctx) {
if(ctx.type == 'label') {
let gText = $(ctx.group._node).find('text');
let ctxHeight = ctx.element.height();
gText.each(function(index, ele){
let item = $(ele);
let diff = ctx.element.attr('dy') - item.attr('dy');
if(diff == 0) {
return false;
}
if(Math.abs(diff) < ctxHeight) {
ctx.element.attr({dy: ctx.element.attr('dy') - ctxHeight});
}
});
}
});
};
}
and then:
new Chartist.Pie(element, data, options).resolveOverlap();
- [Chartjs]-TimeSeries scale in ChartJS 3.0.2. brings error "This method is not implemented: either no adapter can be found or an incomplete integration was …"
- [Chartjs]-Chart.js pie tooltip getting cut
Source:stackexchange.com