【问题标题】:svg rendering order of lines and shapes when using d3使用 d3 时线条和形状的 svg 渲染顺序
【发布时间】:2016-09-26 05:19:37
【问题描述】:

我对svg的理解是先创建的元素先绘制,后面的元素绘制在前面的元素之上(painter的算法)。

我正在制作一个树状的可视化,由组组成,每个组都是一家公司。每组有 5 个元素。首先,时间线有一条直线,每一端都有圆圈,包括公司的起点和终点。

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

所有这些都在 d3 中的 <g> 标记内工作(文本位于圆圈的顶部,圆圈位于线条的顶部)。

但是,此行为不适用于组。文本可能在自己的获取行之前,但在其他行之后。

例子:

在这里,文本位于其组中路径的前面,但位于其他组的行后面,即使文本应该是添加到整个 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);

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

【问题讨论】:

    标签: javascript angularjs d3.js svg


    【解决方案1】:

    前台和后台的顺序不依赖于何时通过 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> ...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-18
      • 1970-01-01
      • 2013-09-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-23
      相关资源
      最近更新 更多