'用m3繪製縮進的樹。我從Mike Rostock's code開始,並做了一些修改,以便:1)顯示除葉子外的向右/向下箭頭; 2)爲每一行添加一個複選框; 3)隱藏根節點。用d3繪製一個可縮進的縮進樹d3
代碼在下面,它接受任何數據,我使用兩個參數調用drawIntentedTree函數:根節點和樹在其中繪製的div ID。
隨着上的圖片可能會看到,也有代碼的一些問題,對於這幫助將不勝感激: 1根/啓動節點,而花費樹枝,導致重繪在重疊左和下箭頭時,請參閱SCL線。 2.使用複選框可以觀察到類似的問題,該複選框基本上是用白色透明的x隱藏的。我的第一個意圖是用筆畫顏色填充框,但必須弄清楚每一行的css顏色是什麼,因爲它改變了。除了解決這兩個問題之外,我還有意圖在節點之間繪製直線,但原始代碼會繪製捲曲線,並允許摺疊和消耗之間的中間狀態(部分摺疊),同時以45°旋轉的箭頭,只顯示分支中的選中框。此外,我希望分支在展開另一分支時摺疊或部分摺疊,以避免向下滾動。
Mike Bostock正在使用一種技巧來顯示/隱藏樹的一部分,他在_children中備份子項,然後將子項分配給null以隱藏摺疊的分支,但重繪始終始於根節點,並且我沒有設法:1)避免根節點重繪; 2)將預先存在的左側三角形旋轉90或90°。
在一篇文章中的許多問題,我會很感激任何部分的幫助。 jsfiddle link。
d3js代碼:
function drawIndentedTree(root, wherein) {
var width = 300, minHeight = 800;
var barHeight = 20, barWidth = 50;
var margin = {
top: -10,
bottom: 10,
left: 0,
right: 10
}
var i = 0, duration = 200;
var tree = d3.layout.tree()
.nodeSize([0, 20]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("#"+wherein).append("svg")
.attr("width", width + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// set initial coordinates
root.x0 = 0;
root.y0 = 0;
// collapse all nodes recusively, hence initiate the tree
function collapse(d) {
d.Selected = false;
if (d.children) {
d.numOfChildren = d.children.length;
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
else {
d.numOfChildren = 0;
}
}
root.children.forEach(collapse);
update(root);
function update(source) {
// Compute the flattened node list. TODO use d3.layout.hierarchy.
var nodes = tree.nodes(root);
height = Math.max(minHeight, nodes.length * barHeight + margin.top + margin.bottom);
d3.select("svg").transition()
.duration(duration)
.attr("height", height);
d3.select(self.frameElement).transition()
.duration(duration)
.style("height", height + "px");
// Compute the "layout".
nodes.forEach(function(n, i) {
n.x = i * barHeight;
});
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) {
return d.index || (d.index = ++i); });
var nodeEnter = node.enter().append("g").filter(function(d) { return d.id != root.id })
.attr("class", "node")
.style("opacity", 0.001)
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
});
// Enter any new nodes at the parent's previous position.
nodeEnter.append("path").filter(function(d) { return d.numOfChildren > 0 && d.id != root.id })
.attr("width", 9)
.attr("height", 9)
.attr("d", "M -3,-4, L -3,4, L 4,0 Z")
.attr("class", function(d) { return "node "+d.type; })
.attr("transform", function(d) {
if (d.children) {
return "translate(-14, 0)rotate(90)";
}
else {
return "translate(-14, 0)rotate(0)";
}
})
.on("click", click);
// Enter any new nodes at the parent's previous position.
nodeEnter.append("rect").filter(function(d) { return d.id != root.id })
.attr("width", 11)
.attr("height", 11)
.attr("y", -5)
.attr("class", function(d) { return "node "+d.type; });
// check box filled with 'x' or '+'
nodeEnter.append("text")
.attr("dy", 4)
.attr("dx", 2)
.attr("class", function(d) { return "node "+d.type+" text"; })
.text("x");
nodeEnter.append("rect").filter(function(d) { return d.parent })
.attr("width", 9)
.attr("height", 9)
.attr("x", 1)
.attr("y", -4)
.attr("class", "node select")
.attr("style", function(d) { return "fill: "+boxStyle(d) })
.on("click", check);
nodeEnter.append("text")
.attr("dy", 5)
.attr("dx", 14)
.attr("class", function(d) { return "node "+d.type+" text"; })
.text(function(d) { return d.Name; });
// Transition nodes to their new position.
nodeEnter.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
.style("opacity", 1);
node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; })
.style("opacity", 1)
.select("rect");
// Transition exiting nodes to the parent's new position.
node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
.style("opacity", 1e-6)
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
// Toggle children on click.
function click(d) {
if (d.children) {
d3.select(this).attr("translate(-14, 0)rotate(90)");
d._children = d.children;
d.children = null;
} else if (d._children) {
d.children = d._children;
d._children = null;
}
update(d);
}
// Toggle check box on click.
function check(d) {
d.Selected = !d.Selected;
d3.select(this).style("fill", boxStyle(d));
}
function boxStyle(d) {
return d.Selected ? "transparent" : "white";
}
}
var wherein = "chart";
var root = {
"name": "AUT-1",
"children": [
{
"name": "PUB-1","children": [
{"name": "AUT-11","children": [
{"name": "AFF-111"},
{"name": "AFF-112"}
]},
{"name": "AUT-12","children": [
{"name": "AFF-121"}
]},
{"name": "AUT-13","children": [
{"name": "AFF-131"},
{"name": "AFF-132"}
]},
{"name": "AUT-14","children": [
{"name": "AFF-141"}
]}
]
},
{
"name": "PUB-2","children": [
{"name": "AUT-21"},
{"name": "AUT-22"},
{"name": "AUT-23"},
{"name": "AUT-24"},
{"name": "AUT-25"},
{"name": "AUT-26"},
{"name": "AUT-27"},
{"name": "AUT-28","children":[
{"name": "AFF-281"},
{"name": "AFF-282"},
{"name": "AFF-283"},
{"name": "AFF-284"},
{"name": "AFF-285"},
{"name": "AFF-286"}
]}
]
},
{"name": "PUB-3"},
{
"name": "PUB-4","children": [
{"name": "AUT-41"},
{"name": "AUT-42"},
{"name": "AUT-43","children": [
{"name": "AFF-431"},
{"name": "AFF-432"},
{"name": "AFF-433"},
{"name": "AFF-434","children":[
{"name": "ADD-4341"},
{"name": "ADD-4342"},
]}
]},
{"name": "AUT-44"}
]
}
]
};
CSS:
.node {
font: 12px sans-serif;
fill: #ccebc5;
stroke: #7c9b75;
stroke-width: 1px;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
cursor: pointer;
}
.node rect {
width: 11px;
height: 11px;
cursor: pointer;
}
.node.select {
width: 9px;
height: 9px;
cursor: pointer;
fill: red;
stroke-width: 0px;
}
.node path {
width: 11px;
height: 11px;
cursor: pointer;
}
.node text Panel {
stroke: #08519c;
stroke-width: 0.5px;
}
.node text Cell {
stroke: #a50f15;
stroke-width: 0.5px;
}
.node.Root {
fill: #f7f7f7;
stroke: #505050;
stroke-width: 1.0px;
}
.node.Root.text {
fill: #505050;
stroke-width: 0px;
font-size: 10px;
font-family: sans-serif;
}
.node.Panel {
fill: #eff3ff;
stroke: #08519c;
stroke-width: 1.0px;
}
.node.Panel.text {
fill: #08519c;
stroke-width: 0px;
font-size: 12px;
font-family: sans-serif;
}
.node.Cell {
fill: #fee5d9;
stroke: #a50f15;
stroke-width: 1.0px;
}
.node.Cell.text {
fill: #a50f15;
stroke-width: 0px;
font-size: 12px;
font-family: sans-serif;
}
你能和你的'styles'更新您的問題,您的數據爲例:修改後的代碼![enter image description here](https://i.stack.imgur.com/XcjMg.png)
塊? – Mark
我認爲這個說法不太正確,「但重繪始終始於根節點」。輸入節點最初是在根的位置開始的,但僅適用於根節點的子節點。後來每個節點都在其父母位置啓動(因爲'click'功能中的update(d)')。還值得注意的是,更新節點的html不會重新生成。所以他們開始他們的位置,然後轉換(翻譯)到他們的新職位(參見塊註釋爲//轉移節點到他們的新位置)。 – mehmet