prevent zero% slices from rendering in pie chart

This commit is contained in:
darshanr0107
2025-06-16 19:11:29 +05:30
parent 6979aa1013
commit cfbce54638

View File

@@ -10,20 +10,14 @@ import { cleanAndMerge, parseFontSize } from '../../utils.js';
import type { D3Section, PieDB, Sections } from './pieTypes.js'; import type { D3Section, PieDB, Sections } from './pieTypes.js';
const createPieArcs = (sections: Sections): d3.PieArcDatum<D3Section>[] => { const createPieArcs = (sections: Sections): d3.PieArcDatum<D3Section>[] => {
// Compute the position of each group on the pie: const sum = [...sections.values()].reduce((acc, val) => acc + val, 0);
const pieData: D3Section[] = [...sections.entries()] const pieData: D3Section[] = [...sections.entries()]
.map((element: [string, number]): D3Section => { .map(([label, value]) => ({ label, value }))
return { .filter((d) => (d.value / sum) * 100 >= 1) // Remove values < 1%
label: element[0], .sort((a, b) => b.value - a.value);
value: element[1],
}; const pie: d3.Pie<unknown, D3Section> = d3pie<D3Section>().value((d) => d.value);
})
.sort((a: D3Section, b: D3Section): number => {
return b.value - a.value;
});
const pie: d3.Pie<unknown, D3Section> = d3pie<D3Section>().value(
(d3Section: D3Section): number => d3Section.value
);
return pie(pieData); return pie(pieData);
}; };
@@ -89,13 +83,21 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
themeVariables.pie11, themeVariables.pie11,
themeVariables.pie12, themeVariables.pie12,
]; ];
let sum = 0;
sections.forEach((section) => {
sum += section;
});
// Filter out arcs that would render as 0%
const filteredArcs = arcs.filter((datum) => ((datum.data.value / sum) * 100).toFixed(0) !== '0');
// Set the color scale // Set the color scale
const color: d3.ScaleOrdinal<string, 12, never> = scaleOrdinal(myGeneratedColors); const color: d3.ScaleOrdinal<string, 12, never> = scaleOrdinal(myGeneratedColors);
// Build the pie chart: each part of the pie is a path that we build using the arc function. // Build the pie chart: each part of the pie is a path that we build using the arc function.
group group
.selectAll('mySlices') .selectAll('mySlices')
.data(arcs) .data(filteredArcs)
.enter() .enter()
.append('path') .append('path')
.attr('d', arcGenerator) .attr('d', arcGenerator)
@@ -104,15 +106,11 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
}) })
.attr('class', 'pieCircle'); .attr('class', 'pieCircle');
let sum = 0;
sections.forEach((section) => {
sum += section;
});
// Now add the percentage. // Now add the percentage.
// Use the centroid method to get the best coordinates. // Use the centroid method to get the best coordinates.
group group
.selectAll('mySlices') .selectAll('mySlices')
.data(arcs) .data(filteredArcs)
.enter() .enter()
.append('text') .append('text')
.text((datum: d3.PieArcDatum<D3Section>): string => { .text((datum: d3.PieArcDatum<D3Section>): string => {
@@ -133,15 +131,20 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
.attr('class', 'pieTitleText'); .attr('class', 'pieTitleText');
// Add the legends/annotations for each section // Add the legends/annotations for each section
const allSectionData: D3Section[] = [...sections.entries()].map(([label, value]) => ({
label,
value,
}));
const legend = group const legend = group
.selectAll('.legend') .selectAll('.legend')
.data(color.domain()) .data(allSectionData)
.enter() .enter()
.append('g') .append('g')
.attr('class', 'legend') .attr('class', 'legend')
.attr('transform', (_datum, index: number): string => { .attr('transform', (_datum, index: number): string => {
const height = LEGEND_RECT_SIZE + LEGEND_SPACING; const height = LEGEND_RECT_SIZE + LEGEND_SPACING;
const offset = (height * color.domain().length) / 2; const offset = (height * allSectionData.length) / 2;
const horizontal = 12 * LEGEND_RECT_SIZE; const horizontal = 12 * LEGEND_RECT_SIZE;
const vertical = index * height - offset; const vertical = index * height - offset;
return 'translate(' + horizontal + ',' + vertical + ')'; return 'translate(' + horizontal + ',' + vertical + ')';
@@ -151,20 +154,18 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
.append('rect') .append('rect')
.attr('width', LEGEND_RECT_SIZE) .attr('width', LEGEND_RECT_SIZE)
.attr('height', LEGEND_RECT_SIZE) .attr('height', LEGEND_RECT_SIZE)
.style('fill', color) .style('fill', (d) => color(d.label))
.style('stroke', color); .style('stroke', (d) => color(d.label));
legend legend
.data(arcs)
.append('text') .append('text')
.attr('x', LEGEND_RECT_SIZE + LEGEND_SPACING) .attr('x', LEGEND_RECT_SIZE + LEGEND_SPACING)
.attr('y', LEGEND_RECT_SIZE - LEGEND_SPACING) .attr('y', LEGEND_RECT_SIZE - LEGEND_SPACING)
.text((datum: d3.PieArcDatum<D3Section>): string => { .text((d) => {
const { label, value } = datum.data;
if (db.getShowData()) { if (db.getShowData()) {
return `${label} [${value}]`; return `${d.label} [${d.value}]`;
} }
return label; return d.label;
}); });
const longestTextWidth = Math.max( const longestTextWidth = Math.max(