admin管理员组

文章数量:1123509

I'm working with a D3 pie chart in a React component where I have a maximum of 8 labels. However, I'm experiencing overlapping between the polylines and the labels when the values are very close to each other. Here's the relevant code snippet:

const data = [
      {change: 0.26, color: '#E6E9D3', label: 'Label 1', value: 20.61},
      {change: 0.2, color: '#E6DAB9', label: 'Label 2', value: 18.78},
      {change: 0, color: '#D9BE9E', label: 'Label 3', value: 24.57},
      {change: 0.18, color: '#C39D82', label: 'Label 4', value: 24.29},
      {change: -0.62, color: '#F2D7D5', label: 'Label 5', value: 10.79},
      {change: -0.01, color: '#9B5C2F', label: 'Label 6', value: 0.97}
    ];


const pie = d3.pie<ReportChartDataItem>().value((d) => d.value)(data);
const arc = d3
  .arc<d3.PieArcDatum<ReportChartDataItem>>()
  .innerRadius(innerRadius)
  .outerRadius(outerRadius);

svg.selectAll("polyline")
      .data(pie)
      .enter()
      .append("polyline")
      .attr("points", (d) => {
        const pos = arc.centroid(d);
        pos[0] = outerRadius * 2.15 * (midAngle(d) < Math.PI ? 1 : -1);
        const posB = [pos[0], pos[1]];
        return [arc.centroid(d), posB]
          .map((point) => point.join(","))
          .join(" ");
      })
      .attr("fill", "none")
      .attr("stroke", "#A0AEAC")
      .attr("stroke-width", "1.5px");

svg.selectAll("text")
      .data(pie)
      .enter()
      .append("text")
      .attr("dy", "0.35em")
      .attr("class", "gotham-font-thin")
      .attr("font-size", "14px")
      .attr("fill", "#000000")
      .text(
        (d) =>
          `${d.data.value >= 0 ? "+" : ""}${formatNumber(d.data.value)}% | ${
            d.data.change >= 0 ? "+" : ""
          }${formatNumber(d.data.change)}`
      )
      .attr("transform", (d) => {
        const pos = arc.centroid(d);
        pos[0] = outerRadius * 1.3 * (midAngle(d) < Math.PI ? 1 : -1);
        pos[1] += 10;
        return `translate(${pos})`;
      })
      .style("text-anchor", (d) => (midAngle(d) < Math.PI ? "start" : "end"));

The labels sometimes overlap when the slices are small or close together. I want to ensure a minimum distance between the labels and avoid overlapping while keeping the layout visually appealing. Given that I only have a maximum of 8 labels, I believe it's possible to avoid collisions entirely.

What would be the best approach to adjust the positioning of labels and ensure they don't overlap? Should I be using a force layout, or is there a simpler way to handle this in D3?

Any guidance or suggestions would be greatly appreciated!

本文标签: reactjsHow to Prevent Overlapping Labels in D3 Pie Chart with Maximum 8 LabelsStack Overflow