0

I'm trying to display a sunburst with text. I used the code from a sunburst example and tried to add text to it (worked), but when it updates, my text disappears. I can only get it to display all text or text when loaded then no text. So when it updates, the text is either gone or is not in sync with the data.

Can anybody tell me what is wrong because I don't know anymore.

Original code: http://bl.ocks.org/mbostock/4348373

My adaptions:

    var width = 1060,
    height = 900,
    radius = Math.min(width, height) / 2;

var x = d3.scale.linear()
    .range([0, 2 * Math.PI]);

var y = d3.scale.sqrt()
    .range([0, radius]);

var color = d3.scale.category20c();

var svg = d3.select("body")
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + (height / 2) + ")");

var partition = d3.layout.partition()
    .value(function(d) { return d.size; });

var arc = d3.svg.arc()
    .startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); })
    .endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); })
    .innerRadius(function(d) { return Math.max(0, y(d.y)); })
    .outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); });

d3.json("http://localhost:50043/data.json", function (error, root) {
    if (error) throw error;
    var data = partition.nodes(root);

    var path = svg.selectAll("path")
        .data(partition.nodes(root))
        .enter()
        //.append("g");
        .append("path")
        //.attr("display", function (d) { return d.depth ? null : "none"; })
        .attr("d", arc)
        .style("fill", function (d) { return color((d.children ? d : d.parent).name); })
        .on("click", click);

    var text = svg.selectAll("text")
        .data(data)
        .enter()
        .append("text")
        .classed("label", true)
        .attr("x", function (d) { return d.x; })
        .attr("text-anchor", "middle")
        // translate to the desired point and set the rotation
        .attr("transform", function (d) {
            if (d.depth > 0) {
                return "translate(" + arc.centroid(d) + ")" +
                    "rotate(" + getAngle(d) + ")";
            } else {
                return null;
            }
        })
        .attr("dx", "6") // margin
        .attr("dy", ".35em") // vertical-align
        .attr("pointer-events", "none")
        .text(function (d) { return d.name; });

    function click(data) {
        text.remove();
        text = svg.selectAll("text")
            .data(data)
            .enter()
            .append("text")
            .classed("label", true)
            .attr("x", function(d) { return d.x; })
            .attr("text-anchor", "middle")
            // translate to the desired point and set the rotation
            .attr("transform", function(d) {
                if (d.depth > 0) {
                    return "translate(" + arc.centroid(d) + ")" +
                        "rotate(" + getAngle(d) + ")";
                } else {
                    return null;
                }
            })
            .attr("dx", "6") // margin
            .attr("dy", ".35em") // vertical-align
            .attr("pointer-events", "none")
            .text(function (d) { return d.name; });

        path.transition()
            .duration(750)
            .attrTween("d", arcTween(data));
    }

    function getAngle(d) {
        // Offset the angle by 90 deg since the '0' degree axis for arc is Y axis, while
        // for text it is the X axis.
        var thetaDeg = (180 / Math.PI * (arc.startAngle()(d) + arc.endAngle()(d)) / 2 - 90);
        // If we are rotating the text by more than 90 deg, then "flip" it.
        // This is why "text-anchor", "middle" is important, otherwise, this "flip" would
        // a little harder.
        return (thetaDeg > 90) ? thetaDeg - 180 : thetaDeg;
    }

    function arcTween(d) {
        var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
            yd = d3.interpolate(y.domain(), [d.y, 1]),
            yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
        return function (d, i) {
            return i
                ? function (t) { return arc(d); }
                : function (t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d); };
        };
    }
});

d3.select(self.frameElement).style("height", height + "px");

Update: You can find my code on https://github.com/KenBonny/D3-Chart-Test You can view the handywork on github page: https://kenbonny.github.io/D3-Chart-Test/

Ken Bonny
  • 729
  • 1
  • 9
  • 29

1 Answers1

0

It's because you are not passing any data to click

wirte function click() { instead of function click(data) {

and I think it will work

François Richard
  • 6,817
  • 10
  • 43
  • 78
  • Sorry mate, looked good, but it still just shows the labels at the start and then removes them after the first click. Thanks for trying. :) – Ken Bonny Sep 29 '15 at 15:41
  • Have you also put the class in the first rendering ? – François Richard Sep 29 '15 at 21:01
  • Sorry again mate. I added the .attr("class", ...) below the .attr("text-anchor",...) and now the text just stays there. When I change d3.selectAll(".SunburstText").remove(); (added a . before the SunburstText) it removes the text, but doesn't place it back. – Ken Bonny Sep 30 '15 at 17:23