【问题标题】:Get visible root node in zoomable sunburst在可缩放的旭日形图中获取可见的根节点
【发布时间】:2018-03-27 15:31:59
【问题描述】:

我用标签制作了一个可缩放的旭日形可视化效果(请参阅in action,或查看the code)。当点击一个项目时,最里面的可见节点的标签会向侧面倾斜。我想只为这个节点修复标签,但我还没有找到一种方法来做到这一点。

有没有办法说“如果(当前节点是可见节点的根)”?还有其他想法吗?

完整的可视化:

点击后放大。我想让 'Calm' 节点文本水平:

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    虽然不完美,但您使用的这个修改后的代码版本会在当前选定节点的动画中调整文本并使其水平。

    var width = 960,
      height = 700,
      radius = (Math.min(width, height) / 2) - 10;
    var formatNumber = d3.format(",d");
    var x = d3.scaleLinear()
      .range([0, 2 * Math.PI]);
    var y = d3.scaleLinear()
      .range([0, radius]);
    var color = d3.scaleOrdinal(d3.schemeCategory20);
    var partition = d3.partition();
    function startAngle(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x0))); }
    function endAngle(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x1))); }
    function innerRadius(d) { return Math.max(0, y(d.y0)); }
    function outerRadius(d) { return Math.max(0, y(d.y1)); }
    var arc = d3.arc()
      .startAngle( function(d) { return startAngle(d);  })
      .endAngle(   function(d) { return endAngle(d);    })
      .innerRadius(function(d) { return innerRadius(d); })
      .outerRadius(function(d) { return outerRadius(d); })
    var texttransform = function(d) {
      var translation = y(d.y0);
      var rotation = computeTextRotation(d);
      if (rotation > 90 && rotation < 270) {
        rotation = rotation + 180;
        translation = -translation;
      }
      return (
        "rotate(" + rotation + ")" +
        "translate(" + translation + ",0)"
      );
    }
    var transition = {};
    function calcTransitionPercentage(){
      var now = Date.now()-transition.clockNow;
      if(!transition.delay || now > transition.delay){
        return Math.min(1,(now-(transition.delay||0))/transition.duration);
      }
      return 0;
    }
    function computeTextRotation(d) {
      if (d.depth === 0) {
        return 0;
      }
      var current = x((d.x0 + d.x1)/2);
      var angle = (current - Math.PI / 2) / Math.PI * 180;
      if(transition.node === d){
        angle -= 90 * calcTransitionPercentage();
      }
      return (angle >  90 || angle < 270) ?  angle : 180 + angle ;
    }
    var textanchor = function(d) {
      if (d.depth === 0) {
        return "middle";
      }
      var rotation = computeTextRotation(d);
      return (rotation > 90 && rotation < 270) ? "end" : "start";
    }
    var textdx = function(d) {
      if (d.depth === 0) {
        return 0;
      }
      var rotation = computeTextRotation(d);
      return (rotation > 90 && rotation < 270) ? -6 : 6;
    }
    var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height)
      .append("g")
      .attr("transform", "translate(" + width / 2 + "," + (height / 2) + ")");
    function calcFontSize(d) {
      const xFactor = 12, yFactor = 7.5 ; // stub
      if (d.depth === 0) {
        return "30px";
      }
      // use inner arc len as text height delimiter
      var innerArc = (endAngle(d) - startAngle(d)) * 2 * Math.PI * innerRadius(d);
      var len = (d.y1-d.y0) * radius;
      return Math.min(innerArc / yFactor, len / d.data.textlen * xFactor) + "px";
    }
    function click(d = { x0: 0, x1: 1, y0: 0, y1: 1 }) {
      transition = {clockNow: Date.now(), duration: 750, node: d }
      var trans = svg.transition().duration(750);
      trans.selectAll("path")
        .attrTween("d", function(n) { return function() { return arc(n); }; })
        .tween("scale", function() {
          var xd = d3.interpolate(x.domain(), [d.x0, d.x1]),
          yd = d3.interpolate(y.domain(), [d.y0, 1]),
          yr = d3.interpolate(y.range(), [d.y0 ? 20 : 0, radius]);
          return function(t) {
            x.domain(xd(t));
            y.domain(yd(t)).range(yr(t));
          };
        });
        trans.selectAll("text")
          .attrTween("transform",   function(n) { return function() { return texttransform(n); }; })
          .attrTween("text-anchor", function(n) { return function() { return textanchor(n); }; })
          .attrTween("dx",          function(n) { return function() { return textdx(n); }; })
          .styleTween("font-size",  function(n) { return function() { return calcFontSize(n); }; });
        trans.selectAll("text")
          .delay(400)
          .attrTween("opacity",     function(n) { return function() {
            if (d === n || n.ancestors().includes(d)) {
              return 1;
            } else {
              return 0;
            }
          }; });
    }
    d3.text('https://raw.githubusercontent.com/manooh/NVSee/master/data/feelings_EN.txt', function(error, raw){
      if (error) throw error;
      // replace two-space indentation with pipes
      raw = raw.replace(new RegExp('  ', 'g'), '|');
      //read pipe-delimited data
      var dsv = d3.dsvFormat('|');
      var flatData = dsv.parse(raw);
      var rData = currentNode = tree(flatData);
      rData = d3.hierarchy(rData);
      var nodes = partition(rData
          .sum(function(d) { return 1; }) // each leaf gets a size of 1
          .sort(function(a, b) { d3.ascending(a.name, b.name) }) // not working?
        )
        .descendants();
      g = svg.selectAll("path")
        .data(nodes)
        .enter().append("g");
      path = g.append("path")
        .attr("d", arc)
        .style("fill", function(d, i) {
          var c;
          if (d.depth === 0) {
            return "white";
          } else if (d.depth === 1) {
            c = color((d.children ? d : d.parent).data.name);
          } else if (d.depth > 1) {
            c = d3.color(d.parent.data.color).darker();
          }
          d.data.color = c;
          return c;
        })
        .on("click", click)
        .append("title")
        .text(function(d) { return d.data.name });
      text = g.append("text")
        .style("fill", function(d) {
          if (d.depth === 0) {
            return "#CCC";
          } else {
            return "#FFF";
          }})
        .attr("class", "svglabel")
        .attr("transform",   texttransform)
        .attr("text-anchor", textanchor)
        .attr("dx",  textdx)
        .attr("dy", ".35em") // vertical-align
        .text(function(d) { return d.data.name; })
        .style("font-size", function(d) {
            // hack. save text len as property to make accessible in transiton
            d.data.textlen = this.getComputedTextLength();
            return calcFontSize(d);
          });
      });
    function tree(nodes) {
      var curr, parent, root;
      var lev = 1;
      nodes.forEach(function(d) {
        if (!root) {
          // handle root (first node)
          curr = {
            name:     d.d1,
            children: []
          };
          root   = curr;
          parent = curr;
        } else {
          if (d['d' + (lev+1)]) {
            // handle children
            lev = lev+1;
            parent = curr;
          } else if (d['d' + (lev-1)]) {
            // handle moving up the hierarchy
            lev = lev-1;
            parent = parent.parent;
          } else if (!d['d' + lev]) {
            // if it's neither child, nor moving up, nor a sibling, handle exception
            throw "unhandled tree level";
          }
          curr = {
            name:     d['d' + lev],
            children: []
          };
          curr.parent = parent;
          parent.children.push(curr);
        }
      });
      return root;
    }
    .svglabel {
      font-family: sans-serif;
      pointer-events: none;
    }
    body {
      -webkit-touch-callout: none; /* iOS Safari */
        -webkit-user-select: none; /* Safari */
         -khtml-user-select: none; /* Konqueror HTML */
           -moz-user-select: none; /* Firefox */
            -ms-user-select: none; /* Internet Explorer/Edge */
                user-select: none; /* Non-prefixed version, currently
                                      supported by Chrome and Opera */
    }
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.13.0/d3.js"&gt;&lt;/script&gt;

    【讨论】:

    • 太棒了,谢谢!您输入的额外转换代码没有做任何事情(因为从未设置延迟),所以我只是将 currentNode 保存在 click() 中并稍后使用它。 github.com/manooh/NVSee/commit/…
    猜你喜欢
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多