【问题标题】:How to position text labels on a Sunburst chart with d3.js如何使用 d3.js 在 Sunburst 图表上放置文本标签
【发布时间】:2014-03-24 23:03:09
【问题描述】:

我在尝试将文本定位在基于 d3.js 的 Sunburst 图表的楔形内时遇到问题。即使在缩放时,text 元素似乎也没有按需要定位..

这是我尝试过的代码的简短 sn-p,但没有成功:

    var slices = svg.selectAll(".form")
            .data(function(d) { return data_slices; })
            .enter()
            .append("g");

        slices.append("path")
            .attr("d", arc)
            .attr("id",function(d,i){return d[2]+""+i;})
            .style("fill", function(d) { return color(d[2]);})
            .on("click",animate)
            .attr("class","form")
            .append("svg:title")
            .text(function(d) { return Math.round(d[0]*100)/100 +" , "+ Math.round(d[1]*100)/100; });

       //Something needs to change below....
      slices.append("text")
            .style("font-size", "10px")
            .attr("x", function(d) { return y(d[1]); })
            .attr("transform", function(d) { return "rotate(" + this.parentNode.getBBox().width + ")"; })
            .attr("dx", "6") // margin
            .attr("dy", ".35em") // vertical-align
            .text(function(d){return d[2]})
            .attr("pointer-events","none");

这是图表的小提琴

Fiddle

可能有什么问题?任何人都可以告诉我或指导我如何将<text> 定位在 svg <path> 中。看起来解决方案是对此的一个小调整,但即使尝试了很长时间我也无法做到时间..

任何有关解决方案方向的帮助/评论将不胜感激......在此先感谢......

【问题讨论】:

    标签: javascript jquery svg d3.js sunburst-diagram


    【解决方案1】:

    我认为这接近您的目标:http://jsfiddle.net/4PS53/3/

    所需的更改如下:

    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;
    }
    
    slices.append("text")
        .style("font-size", "10px")
        .attr("x", function(d) { return d[1]; })
         // Rotate around the center of the text, not the bottom left corner
        .attr("text-anchor", "middle")
         // First translate to the desired point and set the rotation
         // Not sure what the intent of using this.parentNode.getBBox().width was here (?)
        .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")" + "rotate(" + getAngle(d) + ")"; })                                    
        .attr("dx", "6") // margin
        .attr("dy", ".35em") // vertical-align
        .text(function(d){return d[2]})
        .attr("pointer-events","none");
    

    现在要让它在参考点发生变化的地方进行缩放,我们需要更多的基础设施。

    1. 使g.form-container 不仅仅是path.form 可见/不可见。这意味着我们不必担心标签会单独消失。 (我添加了form-container 类。)
    2. 计算新点并为其计算centroidrotation。这有点棘手,但不是太难:

      function change_ref(data_point, reference_point) {
          return [
              get_start_angle(data_point, reference_point),
              get_stop_angle (data_point, reference_point),
              data_point[2],
              get_level      (data_point, reference_point)
          ];
      }
      
      // And while doing transitioning the `text.label`:
      
      svg.selectAll('.label')
      .filter(
          function (b)
          {
              return b[0] >= new_ref[0] && b[1] <= new_ref[1] && b[3] >= new_ref[3];
          }
      ).transition().duration(1000)
       .attr("transform", function(b) {
           var b_prime = change_ref(b, d);
           return "translate(" + arc.centroid(b_prime) + ")" + 
                  "rotate("    + getAngle(b_prime) +     ")"; 
       })
      

      我已将label 类添加到text

    更新的演示: http://jsfiddle.net/4PS53/6/


    但是,我认为可能有更好的方法来呈现这些数据,尤其是。如果您允许缩放和平移:D3 put arc labels in a Pie Chart if there is enough space

    【讨论】:

    • @Aditya 我一直在研究如何旋转文本标签,但结果证明这是一个棘手的问题,因为 get_* 函数的初始(未缩放)计算与从arc.* 功能,但缩放后,这两个不同。那么问题只是手动找出正确的质心。今天晚些时候将对此进行调查。
    • @Aditya 更新了答案。
    • 很好,补间后重新计算圆心是关键。谢谢!!
    【解决方案2】:

    我对 musicly_ut 代码做了一些改进。

    现在您可以从一种数据更改为另一种数据。

                    $('#change').click(function () {
                    if (animating) {
                        return;
                    }
    
                    if (currentSet == 0) {
                        currentSet = 1;
                        svg.selectAll(".form").filter(
                                function (d) {
                                    return d[0] >= ref[0] && d[1] <= ref[1] && d[level_index] >= ref[level_index];
                                }
                            )
                             .transition().duration(1000)
                            .attrTween("d", changeDatarebaseTween(0, 1, 2, 3));
    
                        svg.selectAll('.label').filter(
                                function (d) {
                                    return d[0] >= ref[0] && d[1] <= ref[1] && d[level_index] >= ref[level_index];
                                }
                            )
                             .transition().duration(1000)
                             .attr("transform", function (b) {
                                 var b_prime = change_ref_CD(b);
                                 return "translate(" + arc.centroid(b_prime) + ")" +
                                        "rotate(" + getAngle(b_prime) + ")";
                             })
    
                    }
                    else {
                        currentSet = 0;
                        svg.selectAll(".form").filter(
                                function (d) {
                                    return d[2] >= ref[2] && d[3] <= ref[3] && d[level_index] >= ref[level_index];
                                }
                            )
                             .transition().duration(1000).attrTween("d", changeDatarebaseTween(2, 3, 0, 1));
    
                        svg.selectAll('.label').filter(
                                function (d) {
                                    return d[2] >= ref[2] && d[3] <= ref[3] && d[level_index] >= ref[level_index];
                                }
                            )
                             .transition().duration(1000)
                             .attr("transform", function (b) {
                                 var b_prime = change_ref_CD(b);
                                 return "translate(" + arc.centroid(b_prime) + ")" +
                                        "rotate(" + getAngle(b_prime) + ")";
                             })
                    }
    
                    setTimeout(function () {
                        animating = false;
                    }, 1000);
                });
    

    编辑:http://jsfiddle.net/k1031ogo/3/

    (代码可能更干净,复制/粘贴过多)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-15
      • 2015-07-05
      • 2017-05-03
      • 2018-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多