I'm submitting a ... (check one with "x")
ngx-charts tag) or the gitter chat for support questionsCurrent behavior
The pie chart only shows colour for each segment, would be great to present a percentage label within the segment. (like in #687)
What is the motivation / use case for changing the behavior?
Better illustration
I've made a hack, it will draw the percentage based on each slice's position.
I've never played with svg before, not sure if it's correct way to do it. At least it works:)
Here is the code:
private drawOnPieChart() {
// get the ngx chart element
let node = this.basicPieChart.chartElement.nativeElement;
let svg;
for (let i = 0; i < 5; i++) {
if (i === 3) {
// this is the pie chart svg
svg = node.childNodes[0];
}
// at the end of this loop, the node should contain all slices in its children node
node = node.childNodes[0];
}
// clear the previous text if any
this.textArray.forEach(i => {
if (svg.childNodes[1]) {
svg.removeChild(svg.childNodes[1]);
}
});
// get all the slices
const slices: HTMLCollection = node.children;
for (let i = 0; i < slices.length; i++) {
// calculate the percentage
const value = this.data[i].value;
const percent = Math.floor((value / this.pieDataTotal) * 100);
if (percent > 10) {
const text = this.generateText(slices.item(i), percent);
this.textArray.push(text);
svg.append(text);
}
}
// this is a timeout, less redraw on div resize
this.textRedraw = null;
}
private generateText(g, value) {
// get boundaries
const bbox = g.getBBox();
let x = bbox.x + bbox.width / 2;
let y = bbox.y + bbox.height / 2;
// create text element
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
// sometimes the text draw on the center of the pie, like when 60%
// adjust it slightly
if (x <= 10 && x >= 0) {
x = 50;
}
if (y <= 10 && y >= 0) {
y = 50;
}
text.setAttribute('x', '' + x);
text.setAttribute('y', '' + y);
text.setAttribute('fill', 'white');
text.textContent = value + '%';
text.setAttribute('text-anchor', 'middle');
return text;
}
I used a timeout to redraw the percentage when resize the div.
Here is how it looks:

Updates on this? Is there a better way for this?
Are there any updates on this?
Any updates on the issue?
I am also interested in this feature!
Me too!
I've made a hack, it will draw the percentage based on each slice's position.
I've never played with svg before, not sure if it's correct way to do it. At least it works:)
Here is the code:private drawOnPieChart() { // get the ngx chart element let node = this.basicPieChart.chartElement.nativeElement; let svg; for (let i = 0; i < 5; i++) { if (i === 3) { // this is the pie chart svg svg = node.childNodes[0]; } // at the end of this loop, the node should contain all slices in its children node node = node.childNodes[0]; } // clear the previous text if any this.textArray.forEach(i => { if (svg.childNodes[1]) { svg.removeChild(svg.childNodes[1]); } }); // get all the slices const slices: HTMLCollection = node.children; for (let i = 0; i < slices.length; i++) { // calculate the percentage const value = this.data[i].value; const percent = Math.floor((value / this.pieDataTotal) * 100); if (percent > 10) { const text = this.generateText(slices.item(i), percent); this.textArray.push(text); svg.append(text); } } // this is a timeout, less redraw on div resize this.textRedraw = null; } private generateText(g, value) { // get boundaries const bbox = g.getBBox(); let x = bbox.x + bbox.width / 2; let y = bbox.y + bbox.height / 2; // create text element const text = document.createElementNS('http://www.w3.org/2000/svg', 'text'); // sometimes the text draw on the center of the pie, like when 60% // adjust it slightly if (x <= 10 && x >= 0) { x = 50; } if (y <= 10 && y >= 0) { y = 50; } text.setAttribute('x', '' + x); text.setAttribute('y', '' + y); text.setAttribute('fill', 'white'); text.textContent = value + '%'; text.setAttribute('text-anchor', 'middle'); return text; }I used a timeout to redraw the percentage when resize the div.
Here is how it looks:
How exactly can I use this?
Any update on this?
Any updates?
Any Updates?
Just bumping this, as I am interested in some updates too.
Any updates?
I've made a hack, it will draw the percentage based on each slice's position.
I've never played with svg before, not sure if it's correct way to do it. At least it works:)
Here is the code:```
private drawOnPieChart() {
// get the ngx chart element
let node = this.basicPieChart.chartElement.nativeElement;
let svg;
for (let i = 0; i < 5; i++) {
if (i === 3) {
// this is the pie chart svg
svg = node.childNodes[0];
}
// at the end of this loop, the node should contain all slices in its children node
node = node.childNodes[0];
}
// clear the previous text if any
this.textArray.forEach(i => {
if (svg.childNodes[1]) {
svg.removeChild(svg.childNodes[1]);
}
});
// get all the slices
const slices: HTMLCollection = node.children;
for (let i = 0; i < slices.length; i++) {
// calculate the percentage
const value = this.data[i].value;
const percent = Math.floor((value / this.pieDataTotal) * 100);
if (percent > 10) {
const text = this.generateText(slices.item(i), percent);
this.textArray.push(text);
svg.append(text);
}
}
// this is a timeout, less redraw on div resize
this.textRedraw = null;
}private generateText(g, value) {
// get boundaries
const bbox = g.getBBox();
let x = bbox.x + bbox.width / 2;
let y = bbox.y + bbox.height / 2;
// create text element
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
// sometimes the text draw on the center of the pie, like when 60%
// adjust it slightly
if (x <= 10 && x >= 0) {
x = 50;
}
if (y <= 10 && y >= 0) {
y = 50;
}text.setAttribute('x', '' + x); text.setAttribute('y', '' + y); text.setAttribute('fill', 'white'); text.textContent = value + '%'; text.setAttribute('text-anchor', 'middle'); return text;}
I improved position of the labels, using parametric form of equation of a circle. Someone may be interested in it until there is no such feature in ngx-charts.
(values for my pie chart are already in percents so I don't have calculations of "percent" variable)
private drawOnPieChart() {
let node = this.pieChart.chartElement.nativeElement;
let svg: any;
for (let i = 0; i < 5; i++) {
if (i === 3) {
svg = node.childNodes[0]; // pie chart svg
}
// at the end of this loop, the node should contain all slices in its children node
node = node.childNodes[0];
}
// clear the previous text if any
this.pieChartLabels.forEach(i => {
if (svg.childNodes[1]) {
svg.removeChild(svg.childNodes[1]);
}
});
const slices: HTMLCollection = node.children;
let minX = 0;
let maxX = 0;
for (let i = 0; i < slices.length; i++) {
const bbox = (<any>slices.item(i)).getBBox();
minX = Math.round((bbox.x < minX ? bbox.x : minX) * 10) / 10;
maxX =
Math.round(
(bbox.x + bbox.width > maxX ? bbox.x + bbox.width : maxX) * 10
) / 10;
}
for (let i = 0; i < slices.length; i++) {
const percent = this.data[i].value;
let startingValue = 0;
for (let j = 0; j < i; j++) {
startingValue += this.data[j].value;
}
if (percent >= 2) {
const text = this.generateText(percent, maxX - minX, startingValue);
this.pieChartLabels.push(text);
svg.append(text);
}
}
}
private generateText(percent: number, diagonal: number, startingValue: number) {
// create text element
const text = document.createElementNS('http://www.w3.org/2000/svg', 'text');
const r = Math.round(diagonal / 2.5);
// angle = summed angle of previous slices + half of current slice - 90 degrees (starting at the top of the circle)
const angle = ((startingValue * 2 + percent) / 100 - 0.5) * Math.PI;
const x = r * Math.cos(angle);
const y = r * Math.sin(angle) + 5;
text.setAttribute('x', '' + x);
text.setAttribute('y', '' + y);
text.setAttribute('fill', 'white');
text.textContent = percent + '%';
text.setAttribute('text-anchor', 'middle');
return text;
}
Any updates yet?
any plan to support this feature ?
waiting for this feature.
Any news to this?
Any news to this?
This issue has been opening for 2 years and no update for this requested feature.
My children, please add this to your angular code to add percentages to the labelling:
setTimeout(function(){
let labels = $('.pie-label');
for (let label of labels){
label.innerHTML += "%";
}
}, 100)
It's not ideal, but it works.
You are welcome.
Most helpful comment
My children, please add this to your angular code to add percentages to the labelling:
It's not ideal, but it works.
You are welcome.