简体   繁体   中英

Rendering a D3.js sunburst diagram with Text

I'm trying to modify a sunburst diagram mostly adapted / copied from http://bl.ocks.org/mbostock/4348373 using D3.js. I'm trying to add some text to those arcs (like here: https://www.jasondavies.com/coffee-wheel/ ). How ever, the text just wont be visible. I'm trying to use text-paths. What I've tried:

  • Setting the opacity of the arcs to zero, just to make sure the text isn't hidden somehow
  • Render an arc instead of text, won't be rendered either

Here is the result:

<svg height="700" width="960"><g transform="translate(480, 350)">
  <path style="stroke: rgb(255, 255, 255); fill: rgb(49, 130, 189);" d="M0,202.072594216369A202.072594216369,202.072594216369 0 1,1 0,-202.072594216369A202.072594216369,202.072594216369 0 1,1 0,202.072594216369Z" id="node_0" class="siv_node">
    <title>Tooltip of this arc</title>
    <text class="node_text">
      <textPath xlink:href="#node_0">foobar</textPath>
    </text>
  </path>
  <path style="stroke: rgb(255, 255, 255); fill: rgb(49, 130, 189);" d="M-5.249579602826461e-14,-285.7738033247041A285.7738033247041,285.7738033247041 0 0,1 -5.249579602826461e-14,-285.7738033247041L-3.712013335537173e-14,-202.072594216369A202.072594216369,202.072594216369 0 0,0 -3.712013335537173e-14,-202.072594216369Z" id="node_1" class="siv_node">
    <title>Title of this arc</title>
    <text class="node_text">
      <textPath xlink:href="#node_1">foobar</textPath>
    </text>
  </path>
  ...
</svg>

Here's the part adding the text:

var c = svg.selectAll("path")
  .data(partition.nodes( opt.nodes )).enter()
    .append("path")
    .attr("class", "siv_node")
    .attr("id", function(d, i) { return "node_"+i;});

[...]
c.append("text")
  .attr("class", "node_text")
  .append("textPath")
  .attr("xlink:href", function(d, i) { return "#node_"+i; } )
  .text("foobar");

Thinks I've noticed:

  • When debugging the elements with the Inspector no space is reserved for the text element (like for the path, see screenshot)
  • I've no idea what's going on (I'm new to D3.js and SVG...)

具有预留空间的路径的屏幕截图

Here's the complete code:

renderSunburst: function(opt) {
        // Rendering sunburst diagramm. mostly adapted from:
        // http://bl.ocks.org/mbostock/4063423 and
        // http://bl.ocks.org/mbostock/4348373
        var self = this;
        opt = opt || {};
        opt = this.makeSunburstOptionsValid(opt);

        var stash = function(d) {
            d.x0 = d.x;
            d.dx0 = d.dx;
        };

        // Interpolate the arcs in data space.
        var arcTween = function(a) {
            var i = self.d3.interpolate({x: a.x0, dx: a.dx0}, a);
            return function(t) {
                var b = i(t);
                a.x0 = b.x;
                a.dx0 = b.dx;
                return arc(b);
            };
        };

        var radius = Math.min( opt.size.width, opt.size.height) / 2;
        var formatNumber = d3.format(",d");

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

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

        var arc = this.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)); });

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

        var click = function(d) {
            svg.transition()
                .duration( opt.animation.duration  )
                .tween("scale", function() {
                    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(t) { x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); };
                    })
            .selectAll("path")
                  .attrTween("d", function(d) { return function() { return arc(d); }; });

        };

        var c = svg.selectAll("path")
            .data(partition.nodes( opt.nodes )).enter()
            .append("path")
            .attr("class", "siv_node")
            .attr("id", function(d, i) { return "node_"+i;});

        c.attr("d", arc)
                .style("stroke", "#fff")
                //.attr("fill-opacity", "0")
                .style("fill", function(d) { return color((d.children ? d : d.parent).name); })
                ;// .on("click", click);

        c.append("title")
            .text(function(d) { return d.name + "\n" + formatNumber(d.value); });

        // svg.selectAll(".siv_node")
        //  .data( opt.nodes )
        //  .enter()
        c.append("g").append("text")
            .attr("class", "node_text")
            .style("color", "green")
            .style("fill", "black")
            .attr("stroke", "black")
          .append("textPath")
            .attr("xlink:href", function(d, i) { return "#node_"+i; } )
            .text("foobar");

The text and textpaths don't like being child elements of the path they're referencing, so you need to untangle them like so:

https://jsfiddle.net/ye9ckcbr/

<svg height="700" width="960"><g transform="translate(480, 350)">

  <path style="stroke: rgb(255, 255, 255); fill: rgb(49, 130, 189);" d="M0,202.072594216369A202.072594216369,202.072594216369 0 1,1 0,-202.072594216369A202.072594216369,202.072594216369 0 1,1 0,202.072594216369Z" id="node_0" class="siv_node">
    </path>
    <path style="stroke: rgb(255, 255, 255); fill: rgb(49, 130, 189);" d="M-5.249579602826461e-14,-285.7738033247041A285.7738033247041,285.7738033247041 0 0,1 -5.249579602826461e-14,-285.7738033247041L-3.712013335537173e-14,-202.072594216369A202.072594216369,202.072594216369 0 0,0 -3.712013335537173e-14,-202.072594216369Z" id="node_1" class="siv_node">
    </path>

    <text class="node_text">
     <title>Tooltip of this arc</title>
      <textPath xlink:href="#node_0">foobar</textPath>
    </text>

    <text class="node_text">
        <title>Title of this arc</title>
      <textPath xlink:href="#node_1">foobar</textPath>
    </text>
</svg>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM