繁体   English   中英

在 D3 树布局中使用多种链接类型

[英]Using Multiple Link Types in D3 Tree Layout

我正在使用 Tree Layout 在 D3 v3 中构建一个复杂的图表。 我的图表通常具有树结构,因此我使用对角线链接如下:

var diagonal = d3.svg.diagonal()
  .projection(function (d) {
    return [d.x, d.y];
  });

但是,对于图表中的某些节点,我有不同类型的节点来显示其父节点的属性。 因此,我希望它们与父节点非常接近,而不是与其他子节点处于同一级别。 我认为一个可能的解决方案可能是使用如下径向链接:

var radialDiagonal = d3.svg.diagonal.radial()
  .projection(function (d) {
    return [d.y, d.x / 180 * Math.PI];
  });

但是,我找不到任何关于如何在图表中使用多种链接类型的示例。 是否有可能做到这一点? 或者,是否有任何解决方案可以使某些节点与其父节点如此接近?

提前致谢。

我正在为树使用 d3v4+ 语法,下面的方法相对容易地适用于 v3

听起来您正在寻找使用不同类型链接的能力。

此处的链接类型d3.svg.diaganol与节点放置无关。 该链接仅使用某种预定义的曲线连接两个点。 因此,如果您想允许节点“非常接近其父节点,而不是与其他子节点处于同一级别”,您需要操纵节点的位置,而不是实际的链接。 一种选择是手动移动应该靠近其父节点的节点。 在下面的示例中,我使用节点属性 ( near ) 过滤节点(在运行布局生成器之后)并移动那些应该更靠近其父节点的节点:

 root.descendants().reverse().forEach(function(d) {
  if(d.data.near) d.y = (d.parent.y+d.y)/2;
 })

 var data = { "name": "Parent", "children": [ { "name": "Child A", near:true, "children": [ { "name": "Grandkid A", near: true }, { "name": "Grandkid B" }, { "name": "Grandkid C" } ] }, { "name": "Child B", }, { "name": "Child C", children: [ { "name": "Grandkid D", near:true }, { "name": "Grandkid E" } ]} ] }; var width = 400; var height = 300; margin = {left: 50, top: 10, right:50, bottom: 10} var svg = d3.select("body").append("svg").attr("width", width).attr("height", height); var g = svg.append("g").attr('transform','translate('+ margin.left +','+ margin.right +')'); var root = d3.hierarchy(data); var tree = d3.tree().size([height-margin.top-margin.bottom,width-margin.left-margin.right]); tree(root) root.descendants().reverse().forEach(function(d) { if(d.data.near) dy = (d.parent.y+dy)/2; }) var link = g.selectAll(".link").data(root.links()).enter().append("path").attr("class", "link").attr("d", d3.linkHorizontal().x(function(d) { return dy; }).y(function(d) { return dx; })); 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(" + dy + "," + dx + ")"; }) node.append("circle").attr("r", 2.5); node.append("text").text(function(d) { return d.data.name; }).attr('y',-10).attr('x',-10).attr('text-anchor','middle');
 path{ fill: #fff; stroke: steelblue; stroke-width: 3px; }.link { fill: none; stroke: #ccc; stroke-width: 2px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

上述解决方案非常基本,在具有很多深度的复杂树中,它可能会变得更加困难。 您还可以手动放置每个节点的 x,这提供了更多控制,但代价是编写一个新的算法来替换或纠正至少一半的树布局生成器 output。 最终,“正确”的答案将取决于偏好和数据结构。

如果您想使用不同的链接生成器,这也很容易。 我将使用节点属性(再次near )来指示是否应使用替代链接:

 var data = { "name": "Parent", "children": [ { "name": "Child A", near:true, "children": [ { "name": "Grandkid A", near: true }, { "name": "Grandkid B" }, { "name": "Grandkid C" } ] }, { "name": "Child B", }, { "name": "Child C", children: [ { "name": "Grandkid D", near: true}, { "name": "Grandkid E" } ]} ] }; var width = 400; var height = 300; margin = {left: 50, top: 10, right:50, bottom: 10} var svg = d3.select("body").append("svg").attr("width", width).attr("height", height); var g = svg.append("g").attr('transform','translate('+ margin.left +','+ margin.right +')'); var root = d3.hierarchy(data); var tree = d3.tree().size([height-margin.top-margin.bottom,width-margin.left-margin.right]); tree(root) root.descendants().forEach(function(d) { if(d.data.near) dy = (d.parent.y+dy)/2; }) var horizontal = d3.linkHorizontal().x(function(d) { return dy; }).y(function(d) { return dx; }) // some different path drawing function: var straight = function(d) { return "M"+d.source.y+" "+d.source.x+"L"+(d.target.y-20)+" "+d.source.x+"L"+d.target.y+" "+d.target.x; } var link = g.selectAll(".link").data(root.links()).enter().append("path").attr("class", "link").attr("d", function(d) { if(.d.target.data;near) return straight(d); else return horizontal(d); }). 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.append("text").text(function(d) { return d.data;name. }),attr('y'.-10),attr('x'.-10),attr('text-anchor';'middle');
 path{ fill: #fff; stroke: steelblue; stroke-width: 3px; }.link { fill: none; stroke: #ccc; stroke-width: 2px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM