2016-05-27 3 views
2

Мое понимание svg заключается в том, что сначала создаются элементы, созданные первым, а последующие элементы раскрашены в верхнюю часть предыдущих элементов (алгоритм художника).svg порядок рендеринга линий и фигур при использовании d3

Я делаю древовидную визуализацию, состоящую из групп, каждая из которых является компанией. Каждая группа имеет 5 элементов. Во-первых, существует прямая линия для временной шкалы с кругами на каждом конце, включающая начало и конец компании.

simple company timeline

Тогда есть вертикальная линия, которая крепится к другой окружности на временной шкале компании, приобретенной его.

Все это работает в теге <g> в d3 (текст находится поверх кругов, расположенных поверх строк).

Однако это поведение не распространяется на группы. Текст может быть перед собственной линией сбора, но за линиями других.

Пример:

enter image description here

Здесь текст остается в передней части пути в своей группе, но получает за линиями других групп, даже если текст должен быть последняя часть добавляется ко всему SVG.

Heres соответствующий код:

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

Не думаю, что это делает разницу, но весь этот код находится внутри угловой директивы.

ответ

2

Порядок того, что находится на переднем плане и тем, что в фоновом режиме не зависит от того, когда элементы вставляются через d3.js (иначе создание элемента SVG-DOM и добавление его к SVG документа через API d3.js '), но зависит от порядка в полученном SVG.

Тем не менее, вызов text(node) вызывает текстовые элементы, чтобы быть добавляется в различных g элементов, которые были добавлены в SVG уже который определяет порядок рисования.

Вместо этого я хотел бы добавить все элементы 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> ...

Смежные вопросы