Alexandros K
Alexandros K

Reputation: 947

How to draw labels on Dimple.js donut or pie chart?

Trying to show the percentages right on the donut charts in dimple.plot.pie

Here is some code that kind of works but places the labels right onto the slices.

Having trouble making the labels show up outside the pie.

rings = chart.addSeries("series", dimple.plot.pie);
rings.afterDraw = function(shape, data) {
  var bbox, ctm;
  ctm = shape.getCTM();
  bbox = shape.getBBox();
  return this.chart.svg.append("text")
    .attr("x", ctm.e + bbox.x + bbox.width/2)
    .attr("y", ctm.f + bbox.y + bbox.height/2)
    .text(Math.round(1000*data.piePct)/10 + "%");;
};

Here's the best I can do..

enter image description here

Upvotes: 3

Views: 1660

Answers (2)

RaphaMex
RaphaMex

Reputation: 2839

2 years later and still no solution that works out-of-the-box?

The solution below is a working compilation of all I could find on the topic. Updates are welcome :-)

var pies = chart.addSeries("series", dimple.plot.pie);
pies.radius = 60;
pies.innerRadius = "50%";
pies.afterDraw = function (shape, data) {
    var arc = d3.arc()
        .outerRadius(radius)
        .innerRadius(radius/2);

    var ctm = shape.getCTM();

    chart.svg.append("text")
    // Position text in the centre of the shape
        .attr("x", arc.centroid(data)[0])
        .attr("y", arc.centroid(data)[1])
        .attr("transform", function () {
            return "translate("+ctm.e+","+ctm.f+")";
        })
    // Centre align and nicer display
        .style("text-anchor", "middle")
        .style("font-size", "10px")
        .style("font-family", "sans-serif")
        .style("opacity", 0.8)
    // Prevent text cursor on hover and allow tooltips
        .style("pointer-events", "none")
    // Display text
        .text((data.piePct*100).toFixed(2) + "%)");
}

Upvotes: 1

John Kiernander
John Kiernander

Reputation: 4904

I'd like to build this into the dimple library, but for the time being, here is the method I use in one of my own projects:

function getCentroid(data, plot) {
    var centerX = plot.x + plot.width / 2,
        centerY = plot.y + plot.height / 2,
        angle = (data.startAngle + (data.endAngle - data.startAngle) / 2),
        hyp = (data.innerRadius + (data.outerRadius - data.innerRadius) / 2),
        opp = Math.sin(angle) * hyp,
        adj = Math.cos(angle) * hyp;
    return [centerX + opp, centerY - adj];
}

series.afterDraw = function (shape, data) {
    var ctd = getCentroid(data, plotSize),
        s = d3.select(shape),
        degrees = ((data.startAngle + (data.endAngle - data.startAngle) / 2) * 180) / Math.PI;
    if (degrees < 180) {
        degrees -= 90;
    } else {
        degrees += 90;
    }
    if (Math.abs(data.startAngle - data.endAngle) > 0.1) {
        chart._group.append("text")
            .attr("transform", "rotate(" + degrees + ", " + ctd[0] + ", " +  ctd[1] + 4 + ")")
            .attr("dy", "0.35em")
            .attr("x", ctd[0])
            .attr("y", ctd[1])
            .style("text-anchor", "middle")
            .style("pointer-events", "none")
            .text(format(data.pValue));
    }
};

I took this direct from my own code so it relies on a few variables in scope but hopefully they are fairly self-explanatory.

Upvotes: 3

Related Questions