我是d3的新手,我正在尝试创建this question的可折叠版本 在第4节。在v3中有各种各样的例子可以解释相同,但我找不到适合v4的例子。 我实现了打开子项的onClick函数,但问题是点击后链接放错了位置。它们向右移动,节点保持在同一位置。 请在下面找到我的更新功能代码:
<!DOCTYPE html>
<meta charset="utf-8">
<style>
<!--
.node circle {
//fill: #999;
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text {
font: 10px sans-serif;
}
.node--internal circle {
fill: #555;
}
.node--internal text {
text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
}
.link {
fill: none;
stroke: #555;
stroke-opacity: 0.4;
stroke-width: 1.5px;
}
-->
.node {
cursor: pointer;
}
.node circle {
fill: #999;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font: 10px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
</style>
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script>
var width = 960,
height = 1000,
duration = 750;
var nodes,links;
var i = 0;
var svg = d3.select("body").append("svg")
.attr("width",width)
.attr("height",height);
var g = svg.append("g").attr("transform", "translate(" + (width / 2 + 40) + "," + (height / 2 + 90) + ")");
function connector(d) {
return "M" + project(d.x, d.y)
+ "C" + project(d.x, (d.y + d.parent.y) / 2)
+ " " + project(d.parent.x, (d.y + d.parent.y) / 2)
+ " " + project(d.parent.x, d.parent.y)
/*
return "M" + d.y + "," + d.x +
"C" + (d.y + d.parent.y) / 2 + "," + d.x +
" " + (d.y + d.parent.y) / 2 + "," + d.parent.x +
" " + d.parent.y + "," + d.parent.x; */
}
var treeMap = d3.tree()
.size([360,250]),
root;
var nodeSvg, linkSvg, nodeEnter, linkEnter ;
d3.json("treeData.json",function(error,treeData){
if(error) throw error;
root = d3.hierarchy(treeData,function(d){
return d.children;
});
root.each(function (d) {
console.log(d);
d.name = d.data.name; //transferring name to a name variable
d.id = i; //Assigning numerical Ids
i += i;
});
root.x0 = height / 2;
root.y0 = 0;
function collapse(d) {
if (d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
//root.children.forEach(collapse);
update(root);
});
function update(source) {
//root = treeMap(root);
nodes = treeMap(root).descendants();
//console.log(nodes);
//links = root.descendants().slice(1);
links = nodes.slice(1);
//console.log(links);
var nodeUpdate;
var nodeExit;
// Normalize for fixed-depth.
nodes.forEach(function(d) { d.y = d.depth * 180; });
nodeSvg = g.selectAll(".node")
.data(nodes,function(d) { return d.id || (d.id = ++i); });
//nodeSvg.exit().remove();
var nodeEnter = nodeSvg.enter()
.append("g")
//.attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + project(d.x, d.y) + ")"; })
//.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
.on("click",click)
.on("mouseover", function(d) { return "minu"; });
nodeEnter.append("circle")
.attr("r", 5)
.style("fill", color);
nodeEnter.append("text")
.attr("dy", ".31em")
//.attr("x", function(d) { return d.x < 180 === !d.children ? 6 : -6; })
.attr("x", function(d) { return d.children || d._children ? -10 : 10; })
.style("text-anchor", function(d) { return d.x < 180 === !d.children ? "start" : "end"; })
//.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
.attr("transform", function(d) { return "rotate(" + (d.x < 180 ? d.x - 90 : d.x + 90) + ")"; })
.text(function(d) { return d.data.name; });
// Transition nodes to their new position.
var nodeUpdate = nodeSvg.merge(nodeEnter).transition()
.duration(duration);
// .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
nodeSvg.select("circle")
.style("fill", color);
nodeUpdate.select("text")
.style("fill-opacity", 1);
// Transition exiting nodes to the parent's new position.
var nodeExit = nodeSvg.exit().transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; }) //for the animation to either go off there itself or come to centre
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
linkSvg = g.selectAll(".link")
.data(links, function(link) { var id = link.id + '->' + link.parent.id; return id; });
// Transition links to their new position.
linkSvg.transition()
.duration(duration);
// .attr('d', connector);
// Enter any new links at the parent's previous position.
linkEnter = linkSvg.enter().insert('path', 'g')
.attr("class", "link")
.attr("d", function(d) {
return "M" + project(d.x, d.y)
+ "C" + project(d.x, (d.y + d.parent.y) / 2)
+ " " + project(d.parent.x, (d.y + d.parent.y) / 2)
+ " " + project(d.parent.x, d.parent.y);
});
/*
function (d) {
var o = {x: source.x0, y: source.y0, parent: {x: source.x0, y: source.y0}};
return connector(o);
});*/
// Transition links to their new position.
linkSvg.merge(linkEnter).transition()
.duration(duration)
.attr("d", connector);
// Transition exiting nodes to the parent's new position.
linkSvg.exit().transition()
.duration(duration)
.attr("d", /*function (d) {
var o = {x: source.x, y: source.y, parent: {x: source.x, y: source.y}};
return connector(o);
})*/function(d) {
return "M" + project(d.x, d.y)
+ "C" + project(d.x, (d.y + d.parent.y) / 2)
+ " " + project(d.parent.x, (d.y + d.parent.y) / 2)
+ " " + project(d.parent.x, d.parent.y);
})
.remove();
// Stash the old positions for transition.
}
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
function color(d) {
return d._children ? "#3182bd" // collapsed package
: d.children ? "#c6dbef" // expanded package
: "#fd8d3c"; // leaf node
}
function flatten (root) {
// hierarchical data to flat data for force layout
var nodes = [];
function recurse(node) {
if (node.children) node.children.forEach(recurse);
if (!node.id) node.id = ++i;
else ++i;
nodes.push(node);
}
recurse(root);
return nodes;
}
function project(x, y) {
var angle = (x - 90) / 180 * Math.PI, radius = y;
return [radius * Math.cos(angle), radius * Math.sin(angle)];
}
</script>
</body>
</html>
treeData.json:
{
"name": "United States",
"children": [
{
"name": "Arizona",
"children":[
{ "name" : "Arizona Airport", "size": 13}
]
},
{
"name": "California",
"children":[
{"name": "San Francisco","size":15},
{"name": "San Jose","size":25},
{"name": "Los Angeles","size":17}
]
},
{
"name": "Illinois",
"children":[
{ "name" : "Chicago O'Hare", "size": 13},
{ "name" : "Midway", "size": 18 }
]
},
{
"name": "Colorado",
"children" : [
{ "name": "Denver","size": 7}
]
},
{
"name": "Florida","size":2
},
{
"name": "Georgia", "size": 25
},
{
"name": "Kentucky","size":2
},
{
"name": "Massachussets", "size": 25
},
{
"name": "Michigan","size":2
},
{
"name": "Minnesota", "size": 25
},
{
"name": "Missouri","size":2
},
{
"name": "North Carolina", "size": 25
},
{
"name": "Nevada","size":2
},
{
"name": "Newyork", "size": 12
},
{
"name": "Oregon","size":2
},
{
"name": "Pennsylvania", "size": 25
},
{
"name": "Washington",
"children": [
{ "name" : "Seattle","size" : 13}
]
},
{
"name": "Hawaii", "size": 25
},
{
"name": "Texas",
"children" : [
{ "name": "Dallas" ,"size": 9},
{ "name": "Houston" ,"size": 13},
{ "name": "Austin" ,"size": 17}
]
},
{
"name": "Utah", "size": 25
},
{
"name": "Virginia", "size": 25
}
]
}
答案 0 :(得分:3)
@Minu没有更新问题中的代码,所以这就是我为了让它发挥作用所做的一切:
只需改变:
// Transition nodes to their new position.
var nodeUpdate = nodeSvg.merge(nodeEnter).transition()
.duration(duration);
到此:
// Transition nodes to their new position.
var nodeUpdate = nodeSvg.merge(nodeEnter).transition()
.duration(duration)
.attr("transform", function(d) { return "translate(" + project(d.x, d.y) + ")"; });
希望这对想要使径向树可折叠的其他人有所帮助。