但我希望包含添加,编辑和删除按钮,以便动态管理树。 这是我想要包含的内容的另一张图片。
代码如下所示:
var treeData =data;
console.log(treeData)
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 120
},
width = 960 - margin.right - margin.left,
height = 500 - margin.top - margin.bottom;
var i = 0;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [/*width -*/ d.y + 30, d.x + 25]; });
var svg = d3.select("#tree").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
root = treeData[0];
update(root);
function update(source) {
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = width-(d.depth * 180); });
// Declare the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d) { return d.id || (d.id = ++i); });
// Enter the nodes.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")"; });
/* nodeEnter.append("circle")
/!*nodeEnter.append("new-div")*!/
.attr("r", 20)
.style("fill", "#fff");*/
nodeEnter.append("rect")
.attr("width", 100)
.attr("height", 40)
.attr("stroke", "black")
.attr("stroke-width", 1)
.style("fill", function (d) {
return d._children ? "lightsteelblue" : "#fff";
});
/* nodeEnter.append("text")
.attr("y", function(d) {
return d.children || d._children ? -18 : 18; })
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.name; })
.style("fill-opacity", 1);*/
nodeEnter.append("text")
.attr("x", 100 / 2)
.attr("y", 40 / 2)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function (d) {
return d.name;
});
// Declare the links…
var link = svg.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
// Enter the links.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", diagonal);
}
在html文件中我只有
<div id="tree">
</div>
答案 0 :(得分:1)
我在网上找到了一个小提琴并编辑它以向您展示您想要的基本版本:http://jsfiddle.net/reko91/JnNwu/729/
这是主要代码:
var nodeWidth = 300, nodeHeight = 100;
var buttonWidth = nodeWidth/3;
//container
nodeEnter.append("rect")
.attr('class','buttonContainer')
.attr("width", nodeWidth)
.attr("height", nodeHeight)
.style("fill", 'lightsteelblue')
.attr('transform', 'translate(0,'+(-nodeHeight/2)+')');
//buttonAdd
nodeEnter.append("rect")
.attr('class','addButton')
.attr("width", buttonWidth)
.attr("height", nodeHeight/1.5)
.style("fill",'white')
.attr('transform', 'translate(' + nodeHeight/6 + ','+(-nodeHeight/2 + nodeHeight/6)+')')
.on('click', function(d){
console.log('addButton')
})
;
//buttonDelete
nodeEnter.append("rect")
.attr('class','deleteButton')
.attr("width", buttonWidth)
.attr("height", nodeHeight/1.5)
.style("fill",'red')
.attr('transform', 'translate(' + (nodeWidth - buttonWidth- nodeHeight/6 )+ ','+(-nodeHeight/2 + nodeHeight/6)+')')
.on('click', function(d){
console.log('deleteButton')
})
;
我在这里所做的是,为每个节点添加了一个包含添加和删除按钮的容器(您可以轻松添加编辑)。点击后,他们会控制台记录相应的功能。所以添加日志addButton
等等。
现在实现每个按钮的正确功能:)
var json =
{
"name": "Base",
"children": [
{
"name": "Type A",
"children": [
{
"name": "Section 1",
"children": [
{"name": "Child 1"},
{"name": "Child 2"},
{"name": "Child 3"}
]
},
{
"name": "Section 2",
"children": [
{"name": "Child 1"},
{"name": "Child 2"},
{"name": "Child 3"}
]
}
]
},
{
"name": "Type B",
"children": [
{
"name": "Section 1",
"children": [
{"name": "Child 1"},
{"name": "Child 2"},
{"name": "Child 3"}
]
},
{
"name": "Section 2",
"children": [
{"name": "Child 1"},
{"name": "Child 2"},
{"name": "Child 3"}
]
}
]
}
]
};
var width = 700;
var height = 650;
var maxLabel = 150;
var duration = 500;
var radius = 5;
var i = 0;
var root;
var tree = d3.layout.tree()
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + maxLabel + ",0)");
root = json;
root.x0 = height / 2;
root.y0 = 0;
root.children.forEach(collapse);
function update(source)
{
// Compute the new tree layout.
var nodes = tree.nodes(root).reverse();
var links = tree.links(nodes);
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * maxLabel; });
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function(d){
return d.id || (d.id = ++i);
});
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d){ return "translate(" + source.y0 + "," + source.x0 + ")"; })
//.on("click", click);
var nodeWidth = 300, nodeHeight = 100;
var buttonWidth = nodeWidth/3;
//container
nodeEnter.append("rect")
.attr('class','buttonContainer')
.attr("width", nodeWidth)
.attr("height", nodeHeight)
.style("fill", 'lightsteelblue')
.attr('transform', 'translate(0,'+(-nodeHeight/2)+')');
//buttonAdd
nodeEnter.append("rect")
.attr('class','addButton')
.attr("width", buttonWidth)
.attr("height", nodeHeight/1.5)
.style("fill",'white')
.attr('transform', 'translate(' + nodeHeight/6 + ','+(-nodeHeight/2 + nodeHeight/6)+')')
.on('click', function(d){
alert('Add Button : ' + d.name)
console.log('addButton')
})
;
//buttonDelete
nodeEnter.append("rect")
.attr('class','deleteButton')
.attr("width", buttonWidth)
.attr("height", nodeHeight/1.5)
.style("fill",'red')
.attr('transform', 'translate(' + (nodeWidth - buttonWidth- nodeHeight/6 )+ ','+(-nodeHeight/2 + nodeHeight/6)+')')
.on('click', function(d){
alert('Delete Button : ' + d.name)
console.log('deleteButton')
})
;
nodeEnter.append("text")
.attr("x", function(d){
var spacing = computeRadius(d) + 5;
return d.children || d._children ? -spacing : spacing;
})
.attr("dy", "3")
.attr("text-anchor", function(d){ return d.children || d._children ? "end" : "start"; })
.text(function(d){ return d.name; })
.style("fill-opacity", 0);
// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
nodeUpdate.select("circle")
.attr("r", function(d){ return computeRadius(d); })
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeUpdate.select("text").style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
.remove();
nodeExit.select("circle").attr("r", 0);
nodeExit.select("text").style("fill-opacity", 0);
// Update the links…
var link = svg.selectAll("path.link")
.data(links, function(d){ return d.target.id; });
// Enter any new links at the parent's previous position.
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d){
var o = {x: source.x0, y: source.y0};
return diagonal({source: o, target: o});
});
// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);
// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d){
var o = {x: source.x, y: source.y};
return diagonal({source: o, target: o});
})
.remove();
// Stash the old positions for transition.
nodes.forEach(function(d){
d.x0 = d.x;
d.y0 = d.y;
});
}
function computeRadius(d)
{
if(d.children || d._children) return radius + (radius * nbEndNodes(d) / 10);
else return radius;
}
function nbEndNodes(n)
{
nb = 0;
if(n.children){
n.children.forEach(function(c){
nb += nbEndNodes(c);
});
}
else if(n._children){
n._children.forEach(function(c){
nb += nbEndNodes(c);
});
}
else nb++;
return nb;
}
function click(d)
{
if (d.children){
d._children = d.children;
d.children = null;
}
else{
d.children = d._children;
d._children = null;
}
update(d);
}
function collapse(d){
if (d.children){
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
update(root);
html{
font: 10px sans-serif;
}
svg{
border: 1px solid silver;
}
.node{
cursor: pointer;
}
.node circle{
stroke: steelblue;
stroke-width: 1.5px;
}
.link{
fill: none;
stroke: lightgray;
stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id=tree></div>