1

Hi StackOverflow community. I tried to find the solution for a problem I'm having and was unable to get anything helpful. The closest thing I could find was this which seems to not have a solution. I'm a complete beginner to D3.js so this may also be why I'm having trouble resolving the situation. I tried digging through the documentation as well with no success. So here's my problem. I was trying to do some data visualization stuff and stumbled upon this pie chart in the D3.js example library, which I thought was pretty nifty. Once I started putting a large amount of values into the graph though I noticed I had problems with overlapping labels as can be seen below. I've only altered the code from the example page to make it so I can create multiple charts. Besides that it's essentially the same. Thanks for any help or information anyone can provide!

Overlapping Labels

Community
  • 1
  • 1
wootencl
  • 11
  • 2
  • this should help you https://www.safaribooksonline.com/blog/2014/03/11/solving-d3-label-placement-constraint-relaxing/ – Cyril Cherian Jan 26 '16 at 09:30
  • Possible duplicate of [How to avoid labels overlapping in a D3.js pie chart?](http://stackoverflow.com/questions/19681724/how-to-avoid-labels-overlapping-in-a-d3-js-pie-chart) – Cyril Cherian Jan 26 '16 at 09:31

1 Answers1

3

This will work only for d3 v4. The idea is to compare each node with the rest and move its position if collision is detected. The following code snippet uses this.texts as d3 selection of the labels. Once a collision is detected the element will be moved below - might not be optimised for a specific case.

const nodes = this.texts.nodes();
  for (let i = 0; i < nodes.length; i++) {
    for (let j = i + 1; j < nodes.length; j++) {
      const previous = nodes[i];
      const elem = nodes[j];
      const thisbb = elem.getBoundingClientRect(),
        prevbb = previous.getBoundingClientRect();
      if (!(thisbb.right < prevbb.left ||
        thisbb.left > prevbb.right ||
        thisbb.bottom < prevbb.top ||
        thisbb.top > prevbb.bottom)) {
        const matrix = previous.transform.baseVal.consolidate().matrix;
        d3.select(elem).attr('transform', `translate(${matrix.e}, ${matrix.f + prevbb.bottom - prevbb.top})`);

      }
      const elemMatrix = elem.transform.baseVal.consolidate().matrix;
      pieData[j].pos = [elemMatrix.e, elemMatrix.f];
    }
  }