在D3 zoomable sunburst中,如何根据缩放级别进行标注?

时间:2014-01-25 12:22:34

标签: javascript d3.js sunburst-diagram

我正在尝试使用可缩放的旭日形图来可视化大型数据库。我的json的较低层级中有太多孩子,因此文本标签在外边缘非常混乱且不可读。

我可以根据它们的绝对深度水平打开或关闭标签,但这意味着即使我缩放也不会显示这些标签。

我的问题是,如何计算特定缩放级别的“相对”深度,然后根据它显示标签?

据我所知,d.depth仅表示绝对等级。

2 个答案:

答案 0 :(得分:4)

我假设你是在杰森戴维斯的example工作。

他脚本中的相关代码是

  function click(d) {
    path.transition()
      .duration(duration)
      .attrTween("d", arcTween(d));

    // Somewhat of a hack as we rely on arcTween updating the scales.
    text.style("visibility", function(e) {
          return isParentOf(d, e) ? null : d3.select(this).style("visibility");
        })
      .transition()
        .duration(duration)
        .attrTween("text-anchor", function(d) {
          return function() {
            return x(d.x + d.dx / 2) > Math.PI ? "end" : "start";
          };
        })
        .attrTween("transform", function(d) {
          var multiline = (d.name || "").split(" ").length > 1;
          return function() {
            var angle = x(d.x + d.dx / 2) * 180 / Math.PI - 90,
                rotate = angle + (multiline ? -.5 : 0);
            return "rotate(" + rotate + ")translate(" 
                    + (y(d.y) + padding) + ")rotate(" 
                    + (angle > 90 ? -180 : 0) + ")";
          };
        })
        .style("fill-opacity", function(e) { 
                 return isParentOf(d, e) ? 1 : 1e-6; 
        })
        .each("end", function(e) {
          d3.select(this).style("visibility", 
                    isParentOf(d, e) ? null : "hidden");
        });
  }

请注意其中一些函数如何引用两个不同的数据对象d vs e。这是因为,除非它被内部函数掩盖,否则click函数内的d是被点击元素的数据对象 - 成为圆的中心的元素。

如果他为内部函数赋予数据对象(function(e){})不同的名称,那么这就是与具有已更改属性的单个元素关联的数据对象。因此,他能够调用比较两个数据对象的函数来确定是否应该在该缩放级别隐藏给定元素。

你想要做同样的事情,除了你不仅隐藏文本,如果它是中心轮的父亲,你也隐藏它,如果它太深的后代。所以你需要这样的东西:

          if (e.depth > d.depth + 3) return "hidden";

你添加代码的地方取决于样式选择--Jason Davies实际上是在三个点改变文本不透明度或可见性:在转换之前和之后设置可见性(在“结束”事件期间),不透明度在两者之间消失。您希望标签在点击时弹出和输出,还是希望它们淡入淡出?

答案 1 :(得分:1)

我还不能发表评论,如果你去寻找戴维斯'代码在他身边,找到对这个答案没有帮助的缩小版本 - 完整版本移到这里:https://code.google.com/p/testprogramming/source/browse/trunk/javascript/svg/d3/test/wheel.js?r=394&spec=svn394

上述答案中缺少所有重要的功能isParentOf,必须从完整版本中收集。

- 其他信息: 如果你想让标签显示基于"缩放"另外要注意sunburst不使用.zoom()函数也很重要,你必须手动找到路径。在我的情况下,我想在顶部缩放级别隐藏所有标签,但是如果选择了任何其他级别则显示它们。为此,我在开头隐藏文本然后每次单击我使用以下测试

    var text = g.append("text")
    .attr("class","mylabel")
    .attr("transform", function(d) { return "rotate(" + computeTextRotation(d) + ")"; })
    .attr("x", function(d) { return y(d.y); })
    .attr("dx", "4") // left - margin for text
    .attr("dy", ".25em") // vertical-align of text in cell
    .text(function(d) { return (d.name == 'root') ? ('') : d.name; })
    .attr("font-size", function(d) { return d.ci_type === 'type' ? 12 : 10}) //font-size of text
    //.attr("visibility",function(d) { return d.dx < 0.009? "hidden" : "visible"}) // hide text of labels of partitions less than 2%
    .attr("visibility", "hidden") // hide labels at root level - starting level


    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); })

      }
    });


    // if the vis is at the 'root' level hide text, otherwise show    <! here is the test!  
    var str = d.name;
    var patt = 'root';
    var atRoot = (str === patt) ? true : false ;

    //console.log(atRoot); 

    //console.log( d.name ) ;

    text.attr("visibility",function(d) { return atRoot ? "hidden" : "visible"})  


    // end of click      
     }