D3:在旭日例中旋转第三和第四个四边形中的标签

时间:2014-01-27 22:54:20

标签: javascript d3.js label sunburst-diagram

我在第一次使用D3和javascript绘制旭日形象,遵循http://bl.ocks.org/mbostock/http://bl.ocks.org/mbostock/4063423的示例。第四个和第四个四边形中的标签是颠倒的。我在这里找到了咖啡轮示例http://www.jasondavies.com/coffee-wheel/,并尝试在我的示例中加入,但是在旋转标签时没有成功。我确实在How to properly rotate text labels in a D3 sunburst diagram找到了类似的帖子,但由于其中一个链接无效,因此无法解决问题。

<!DOCTYPE html>
<meta charset="utf-8">
<style>

    path {
        stroke: #fff;
        fill-rule: evenodd;
    }

    text {
        font-family: Arial, sans-serif;
        font-size: 12px;
    }

</style>
<body>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script>

        var width = 1600,
        height = 1300,
        radius = Math.min(width, height) / 2;

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

        var y = d3.scale.linear()
        .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 + 10) + ")");

        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("ex.json", function(error, root) {
            var g = svg.selectAll("g")
            .data(partition.nodes(root))
            .enter().append("g");

            var path = g.append("path")
            .attr("d", arc)
            .style("fill", function(d) { return color((d.children ? d : d.parent).name); })
            .on("click", click);

            var text = g.append("text")
            .attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; })
            .attr("x", function(d) { return y(d.y); })
            .attr("dx", "6") // margin
            .attr("dy", ".35em") // vertical-align
            .text(function(d) { return d.name; });

            function click(d) {
                // fade out all text elements
                text.transition().attr("opacity", 0);

                path.transition()
                .duration(750)
                .attrTween("d", arcTween(d))
                .each("end", function(e, i) {
                      // check if the animated element's data e lies within the visible angle span given in d
                      if (e.x >= d.x && e.x < (d.x + d.dx)) {
                          // get a selection of the associated text element
                          var arcText = d3.select(this.parentNode).select("text");
                          // fade in the text element and recalculate positions
                          arcText.transition().duration(750)
                          .attr("opacity", 1)
                          .attr("transform", function() { return "rotate(" + computeTextRotation(e) + ")" })
                          .attr("x", function(d) { return y(d.y); });
                      }
                });
            }
        });

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

        // Interpolate the scales!
        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); };
            };
        }

        function computeTextRotation(d) {
            return (x(d.x + d.dx / 2) - Math.PI / 2) / Math.PI * 180;
        }

    </script>

ex.json

[{
 "name": "aaa",
 "size": 5000,
 "children":
    [
        {
        "name": "aaab",
        "size": 2952,
        "children": [
                  {"name": "xxx", "size": 45},
                  {"name": "xxy", "size": 29},
                  {"name": "xxz", "size": 28},
                  {"name": "xxa", "size": 4}
                  ]
        },

        {
        "name": "aaac",
        "size": 251,
        "children": [
                        {
                        "name": "ddd",
                        "size": 7,
                        "children": [
                                     {"name": "ppp", "size": 4},
                                     {"name": "qqq", "size": 2}
                                     ]
                        },
                        {"name": "xxt", "size": 4},
                        {"name": "xxu", "size": 1},
                        {"name": "xxv", "size": 1}
                     ]
        },
        {"name": "aaad","size": 222}
     ]
}][1]

1 个答案:

答案 0 :(得分:3)

computeTextRotation功能更改为以下内容:

    function computeTextRotation(d) {
        var ang = (x(d.x + d.dx / 2) - Math.PI / 2) / Math.PI * 180;
        return (ang > 90) ? 180 + ang : ang;
    }

并将旋转点设置为相应圆弧的质心位置:

   var text = g.append("text")
        .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")rotate(" + computeTextRotation(d) + ")"; })
        .attr('text-anchor', function (d) { return computeTextRotation(d) > 180 ? "end" : "start"; })
        .attr("dx", "6") // margin
        .attr("dy", ".35em") // vertical-align
        .text(function(d) { return d.name; });

示例:http://jsfiddle.net/Hm49x/

使用您的数据:http://plnkr.co/edit/tct95toQ2IjyUkQJQPB9?p=preview