簡體   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