使用d3

时间:2016-05-27 19:10:22

标签: javascript angularjs d3.js svg

我对svg的理解是首先绘制的元素首先绘制,后面的元素绘制在前面元素的顶部(painter算法)。

我正在制作一个树状的可视化,由群组成,每个群组都是公司。每组有5个元素。首先,时间轴上有直线,每端有圆圈,包括公司的开始和结束。

simple company timeline

然后,有一条垂直线连接到获得它的公司时间轴上的另一个圆圈。

所有这些都适用于d3中的<g>标记内(文字位于圆圈顶部,位于行顶部)。

但是,这种行为不适用于各组。该文本可能位于其自己的采集线之前,但落后于其他采访线。

示例:

enter image description here

这里,文本保留在其组中的路径前面,但是后面是其他组的行,即使文本应该是添加到整个svg的最后一部分。

见下相关代码:

    function start(root) {
      var duration = d3.event && d3.event.altKey ? 5000: 500;

      var nodes = tree.nodes(root);
      var node = sv.selectAll("g.node")
            .data(nodes, function(d) {return d.id || (d.id = ++i); });

      node.enter().append("svg:g")
        .attr("class", "node")
        .attr("transform", function(d) {
          if(d.depth === 0){
            d.xy = [0, centerline + d.position];
          }
          else{
            d.xy = [(2016-parseInt(d.acquisition_date))*30, centerline + d.position];
          }
          //don't need this anymore
          return "scale(" + 1 + "," + 1 + ")"; });

      function lines(node){
        node.append("svg:line")
          .attr("x1", function(d){
            return d.xy[0];
          })
          .attr("y1", function(d){
            return centerline + d.position;
          })
          .attr("x2",function(d){
            return (2016 - parseInt(d.founded_date))*30;
          })
          .attr("y2", function(d){
            return centerline + d.position;
          })
          .attr("timeline", function(d){
            return d.name;
          })
          .style("stroke", function(k){
            if(k.depth === 0) {
              return "black";
            }
              return "#ccc";
          })
          .style("stroke-width", "2.5");

          node.append("svg:path")
            .filter(function(d){
              if(d.parent){
                d.acquiz = [((2016)- parseInt(d.acquisition_date))*30, centerline + d.parent.position];
              }
              return d.hasOwnProperty('parent');
            })
            .attr("acquired_by", function(d){
              return d.parent.name;
            })
            .attr("acquired", function(d){
              return d.name;
            })
            .attr("d", function(d){
              return "M" + d.xy[0] +"," + d.xy[1] + " L" + d.acquiz[0] + "," +d.acquiz[1];
            })
            .attr("stroke", "#ccc")
            .attr("stroke-width", 2)
            .style("fill", "none");
          }

          function circles(node){
            node.append("svg:circle")
              .attr("cx", function(d){
                return (2016 - parseInt(d.founded_date))*30;
              })
              .attr("cy", function(d){
                return centerline + d.position;
              })
              .attr("r", 4.5)
              .style("fill", function(d){ return d.children ? "white"
              : "white"; });

            node.append("svg:circle")
              .attr("cx", function(d){
                if(d.acquisition_date){
                  return (2016 - parseInt(d.acquisition_date))*30;
                }
                else{
                  return 0;
                }
              })
              .attr("cy", function(d){
                return centerline + d.position;
              })
              .attr("r", 4.5)
              .style("fill", function(d) { return d.children ? "white"
                : "white"; });

              node.append("svg:circle")
                .filter(function(d){
                  return d.hasOwnProperty('parent');
                })
                .attr("cx", function(d){
                  return ((2016 - parseInt(d.acquisition_date))*30);
                })
                .attr("name", function(d){
                  return d.name;
                })
                .attr("cy", function(d){
                  return centerline + d.parent.position;
                })
                .attr("r", 5.5)
                .attr("acq", function(d){return d.name;})
                .style("fill", "lightsteelblue");
              }

        function text(node){
              node.append("svg:a")
                .attr("ng-attr-xlink:href", function(d){
                  return "http://xxxxxxxxxxxx.edu/company/" + encodeURIComponent(d.name);
                })
                .append("svg:text")
                  .attr("x", function(d){
                    return d.refined[0]; })
                  .attr("dy", "1.5em")
                  .attr("y", function(d){
                    return d.refined[1];
                  })
                  .style("fill-opacity", 1)
                  .attr("text-anchor", function(d) { return d.children || d.children ? "middle" : "middle"; })
                    .text(function(d) {
                      return d.name;
                  });
            }

            lines(node);
            circles(node);
            text(node);

不要认为这有所不同,但所有这些代码都在一个角度指令中。

1 个答案:

答案 0 :(得分:2)

前景中的内容和后台内容的顺序不依赖于何时通过 d3.js 插入元素(也就是创建SVG DOM元素并添加它通过d3.js'API)到SVG文档,但取决于生成的 SVG 中的顺序。

也就是说,text(node)的调用会导致文本元素附加到已添加到SVG的各种g元素中,这已决定了绘制顺序

我要尝试的是将所有text元素附加到SVG文档的末尾。会产生类似的结果:

... <g class="node">...</g> <g class="node">...</g> <g class="node">...</g> <g class="text-overlays"> <text>1</text <text>2</text ... </g> ...