How to place labels on dc.js pie chart?

I would like to show labels for tiny fragments ( chart.minAngleForLabel(0.05)

), avoiding text overlap.

I've added a render that shifts the labels along the outer edge:

  .on('renderlet', function(chart) {
      chart.selectAll('text').attr('transform', function(d, i) {
          var old = this.getAttribute('transform');
          if (d.endAngle-d.startAngle > 0.3) { return old; }
          var xy = old.slice(10,-1).split(',');
          var m = 1.25 + (i%3) * 0.25;
          return 'translate(' + (+xy[0]*m) + ',' + (+xy[1]*m) + ')';
      })
     })

      

and I'm happy with it (second image after renderlet):

beforeafter

but it causes annoying transitions - the labels move to the centroid and then bounce back. Is there a workaround for this?

+3


source to share


2 answers


My solution is a bit over the top, but I wanted to know if it is now possible to replace translated positions now that we have a pre-redirect event in dc.js 2.0 beta 11.

This is actually the case. The impractical part is that your code relies on already having end positions, which we won't have if we replace transitions. Instead, we have to calculate the positions from scratch, which means copying a bunch of code from the pie chart.

I was unable to get your code to work, so I just test this by shifting all label positions by -25, -25. But it's the same idea, we use the original code to get the centroid and then modify that position:



// copied from pieChart
function buildArcs(chart) {
    return d3.svg.arc().outerRadius(chart.radius()).innerRadius(chart.innerRadius());
}

function labelPosition(d, arc) {
    var centroid = arc.centroid(d);
    if (isNaN(centroid[0]) || isNaN(centroid[1])) {
        return [0,0];
    } else {
        return centroid;
    }
}
//
        .on('pretransition', function(chart) {
            chart.selectAll('text.pie-slice').transition().duration(chart.transitionDuration())
                .attr('transform', function(d, i) {
                    var arc = buildArcs(chart);
                    var xy = labelPosition(d, arc);
                    return 'translate(' + (+xy[0] - 25) + ',' + (+xy[1] - 25) + ')';
            })
        });

      

The big idea here is that if you specify a new transition for an element, it will replace the already active transition. Thus, we completely remove the original position and transition and replace it with our own. No "jump"!

+4


source


Doesn't quite solve your problem, but might look better with the transition to position?



chart.selectAll('text')
  .transition()
  .delay(800)
  .attr("transform", ...

      

+2


source







All Articles