指定nodeSize时,d3树的居中会发生更改

时间:2017-05-17 00:17:06

标签: d3.js

我正在使用d3.v4。当我有

var treemap = d3.tree().size([height, width])

树很好地居中

enter image description here

但是(因为我想指定节点之间的垂直间距)当我将其更改为

var treemap = d3.tree().size([height, width]).nodeSize([40]);

树移到左上角:

enter image description here

有谁知道为什么会这样?

2 个答案:

答案 0 :(得分:4)

我认为d3.tree().size()d3.tree().nodeSize()相互排斥。设置一个会使另一个无效。 v3文档(here)在这方面是明确的,而v4文档(here)可能表明这仍然是正确的。快速测试表明v4与v4相同。 (另请参阅:this answerthis one。)

更重要的是,"当指定节点大小时,根节点始终位于⟨0,0⟩。" (API documentation)。

使用size时,每个节点的定位利用可用空间 - 相对于指定的宽度/高度进行定位,而不考虑节点密度。使用nodeSize时,定位是相对于其他节点的,而不是图的可用区域(尽管它将锚定在[0,0])。通过最初使用.size,您不必担心定位。使用.nodeSize,您必须为节点设置转换,以便它们正确居中。

要正确定位,您需要在容器上设置变换,以便[0,0]和根节点放置得更合适(如下面的无边距示例中的[ 0,高度/ 2]):



var data = { "name": "Parent", "children": [ { "name": "Child A", "children": [ { "name": "Grandchild" } ] }, { "name": "Child B", } ] };

var width = 500;
var height = 500;
var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height);
	  
var g = svg.append("g").attr('transform','translate(0,'+ (height/2) +')');
var root = d3.hierarchy(data);
	  
var tree = d3.tree()
    .nodeSize([width/2,height/2]);

 var link = g.selectAll(".link")
    .data(tree(root).links())
    .enter().append("path")
      .attr("class", "link")
      .attr("d", d3.linkHorizontal()
          .x(function(d) { return d.y; })
          .y(function(d) { return d.x; }));

  var node = g.selectAll(".node")
    .data(root.descendants())
    .enter().append("g")
      .attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })

  node.append("circle")
      .attr("r", 2.5);

.node circle {
  fill: #fff;
  stroke: steelblue;
  stroke-width: 3px;
}

.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 2px;
}
svg {
	background: #eee;
}

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
&#13;
&#13;
&#13;

d3.tree().size()

的自动间距相比

&#13;
&#13;
var data = { "name": "Parent", "children": [ { "name": "Child A", "children": [ { "name": "Grandchild" } ] }, { "name": "Child B", } ] };

var width = 500;
var height = 500;
var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height);
	  
var g = svg.append("g");
var root = d3.hierarchy(data);
	  
var tree = d3.tree()
    .size([width,height]);

 var link = g.selectAll(".link")
    .data(tree(root).links())
    .enter().append("path")
      .attr("class", "link")
      .attr("d", d3.linkHorizontal()
          .x(function(d) { return d.y; })
          .y(function(d) { return d.x; }));

  var node = g.selectAll(".node")
    .data(root.descendants())
    .enter().append("g")
      .attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })

  node.append("circle")
      .attr("r", 2.5);
&#13;
.node circle {
  fill: #fff;
  stroke: steelblue;
  stroke-width: 3px;
}

.link {
  fill: none;
  stroke: #ccc;
  stroke-width: 2px;
}
svg {
	background: #eee;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.9.1/d3.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

**最简单的方法是**

        document.getElementById("wkgrp").style.transform = "translate(100px, 350px)"

根据需要设置负载转换,以便它可以通过svg动态管理。