代码之家  ›  专栏  ›  技术社区  ›  Florian Baierl

在d3中绘制数据的变更顺序

  •  2
  • Florian Baierl  · 技术社区  · 7 年前

    Node 绘制它们的位置很重要(应该显示在顶部的那些需要最后绘制)。

    这些节点的位置和z轴可能会发生变化,这就是为什么我尝试使用 钥匙 指数

    case class Node(id: Int)
    
    def addNodesToSVG = {
       val sortedData: List[Node] = ??? 
    
       val nodesSelection = d3.select("#nodes").selectAll(".node")
          .data(sortedData.toJSArray, (n: Node) => {
             n.id.toString +
             // the position of those nodes may change over time
             // that's why we need to include the position in the identifier
             sortedData.indexOf(n)
       }
    
       nodesSelection.enter().append("g").attr("class", "node") // ...
    
       nodesSelection
           .attr("transform", transform) // ...
    
       nodesSelection.exit().remove()
    }
    

    理论上,如果我只有两个节点的话,这就是我认为它会起作用的方式( n1 n2 ),它们保存在 List(n1, n2)

    node   key
    -----  ---
    n1      10 // node 1 at position 0
    n2      21 // node 2 at position 1
    

    现在如果我将列表更改为 List(n2, n1) 打电话 addNodesToSVG 这也是我认为会发生的事情:

    node   key
    -----  ---
    n2      20 // node 1 at position 0
    n1      12 // node 2 at position 1
    

    nodesSelection.exit().remove()

    编辑 经过进一步的调试,我发现我的 exit 所选内容的大小始终为0。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Coderino Javarino    7 年前

    我认为id函数应该以一致的方式使用——仅仅因为一个对象改变了它的位置,id函数对它的结果就不应该改变(在我看来,这就是使用它的第一点)。我将采取的方法是使id函数完全依赖于节点的id;向数据对象添加指定渲染顺序的字段;根据新字段对合并后的选择进行排序。

    <!DOCTYPE html>
    <head>
      <meta charset="utf-8">
      <script src="https://d3js.org/d3.v4.min.js"></script>
      <style>
        body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
      </style>
    </head>
    
    <body>
      <button onclick="sw()">Switch</button>
      <script>
        var d1 = [{
          id: 'a',
          z: 1,
          fill: 'red', 
          y: 0
        }, {
          id: 'b',
          z: 2,
          fill: 'green', 
          y: 5
        }];
        
        var d2 = [{
          id: 'a',
          z: 2, 
          fill: 'red',
          y: 5
        }, {
          id: 'b',
          z: 1, 
          fill: 'green',
          y: 0
        }]
        
        var current = 0;
        
        var svg = d3.select("body").append("svg")
          .attr("width", 100)
          .attr("height", 100)
        	.attr('viewBox', '0 0 10 20');
    
        function render(d) {
          var r = svg.selectAll('rect')
          	.data(d, function(d) { return d.id; });
          r.enter()
          	.append('rect')
          	.attr('width', 10)
          	.attr('height', 10)
          	.attr('fill', function(d) { return d.fill; })
          .merge(r)
          	.sort(function(r1, r2) {
            	if (r1.z > r2.z) return 1;
            	if (r1.z < r2.z) return -1;
            	return 0;
          	})
          	.transition()
          	.attr('y', function(d) { return d.y; });
          
          r.exit().remove();
        };
        
        function sw() {
            if (current == 0) {
              current = 1;
              render(d2);
            } else {
              current = 0;
              render(d1);
            }
        }
        
        render(d1);
    
      </script>
    </body>
    推荐文章