我是D3 js的新手。我想用d3绘制树形结构。但是,我希望我的节点之间的路径不像通常的对角线和投影方法那样灵活。我需要节点之间的连接是这样的:
我如何在d3中执行此操作?
这是我目前的对角线代码。
<html>
<head>
<title> Box office </title>
</head>
<body>
<style>
.node {
cursor: pointer;
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 3px;
}
.node text {
font: 12px sans-serif;
}
.link {
fill: none;
stroke: #ccc;
stroke-width: 2px;
}
</style>
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v3.min.js"></script>
<div id = "boxoffice"></div>
<script type="text/javascript">
var sampleData = [
{
"ChangeFlowsFromParent": "false",
"ChangeFlowsToParent": "false",
"StreamType": "Mainline",
"streamName": "ArgOS_2_0",
"Parent": "none",
"Compliance": "Released",
"children": [
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_0_DHAL",
"Parent": "ArgOS_2_0",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_0_Dev",
"Parent": "ArgOS_2_0",
"Compliance": "Released",
"children": [
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "r_ArgOS_0230",
"Parent": "ArgOS_2_0_Dev",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "branch1",
"Parent": "ArgOS_2_0_Dev",
"Compliance": "Released",
"children": [
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "branch100",
"Parent": "branch1",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "branch200",
"Parent": "branch1",
"Compliance": "Released",
"children": [
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "honey",
"Parent": "branch200",
"Compliance": "Released"
}
]
}
]
}
]
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_0_IPC-Tracer",
"Parent": "ArgOS_2_0",
"Compliance": "Released",
"children": [
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "ArgOS_2_0_IPC_child 1",
"Parent": "ArgOS_2_0_IPC",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Release",
"streamName": "ArgOS_2_0_IPC_child 2",
"Parent": "ArgOS_2_0_IPC",
"Compliance": "Released"
}
]
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_0_NSW_Temp",
"Parent": "ArgOS_2_0",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_0_Test",
"Parent": "ArgOS_2_0",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "ArgOS_2_CBD",
"Parent": "ArgOS_2_0",
"Compliance": "Released"
},
{
"ChangeFlowsFromParent": "true",
"ChangeFlowsToParent": "true",
"StreamType": "Development",
"streamName": "test_mergewp",
"Parent": "ArgOS_2_0",
"Compliance": "Released"
}
]
}
]
var margin = {top:100, bottom: 100, left:100, right:100},
width = 1800 - margin.left-margin.right, //total width minus side margins
height = 1500 - margin.top - margin.bottom; //total height minus vertical margins
var tree = d3.layout.tree().size([width, height]);
tree.nodeSize([40,100]);
var diagonal = d3.svg.diagonal()
.projection(function(d) { return [d.x, -d.y]; });
var svgContainer = d3.select("#boxoffice").append("svg").attr("width", width).attr("height", height).append("g").attr("transform", "translate(" + (width/2) + "," + (height - 500) + ")");
var root = sampleData[0];
root.x0 = width/2;
root.y0 = 0;
update(root);
d3.select(self.frameElement).style("height", "500px");
function update(sourceNode){
var nodes = tree.nodes(sourceNode).reverse(),
links = tree.links(nodes);
nodes.forEach(function(d){d.y = d.depth * 180});
var node = svgContainer.selectAll("g.node").attr("class", "node").data(nodes, function(d, i){return d.id || (d.id = ++i); });
var nodeEnter = node.enter().append("g")
.attr("transform", function(d) {
<!-- if(d.StreamType == "Mainline") -->
<!-- return "translate(-100,-100)"; -->
<!-- else -->
return "translate(" + sourceNode.y0 + "," + sourceNode.x0 + ")";
});
nodeEnter.append("circle")
.attr("r", 15)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeEnter.append("text")
.attr("x", function(d) { return d.children || d._children ? -13 : 13; })
.attr("dy", ".35em")
.attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
.text(function(d) { return d.streamName; })
.style("fill-opacity", 1e-6);
var nodeUpdate = node.transition()
.duration(100)
.attr("transform", function(d) {
if(d.StreamType == "Mainline")
{
var lastElement = nodes[0];
return "translate(" + (lastElement.y + 100) + "," + (lastElement.x -130) + ")"; //adding the root element
}
else
return "translate(" + d.y + "," + (d.x-(margin.top + margin.bottom)) + ")";
});
nodeUpdate.select("circle")
.attr("r", 10)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
nodeUpdate.select("text")
.style("fill-opacity", 1);
var link = svgContainer.selectAll("path.link")
.data(links, function(d) { return d.target.id; });
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {x: sourceNode.x0, y: sourceNode.y0};
return diagonal({source: o, target: o});
});
// Transition links to their new position.
link.transition()
.duration(10)
.attr("d", diagonal);
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
function positionLink(d) {
return "M" + d[0].x + "," + d[0].y
+ "S" + d[1].x + "," + d[1].y
+ " " + d[2].x + "," + d[2].y;
}
</script>
</body>
</html>
&#13;
在此代码中,链接都是凌乱的。我可以为对角路径链接整理它,但我希望我的链接是动态和灵活的。我怎样才能做到这一点?
答案 0 :(得分:0)
目前还不清楚你的意思是什么?&#34;灵活的&#34;。可以从https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths#Bezier_Curves收集更准确的术语。例如,您可能需要一个三次贝塞尔曲线。
要实现这一点,您需要更改此部分代码:
.attr("d", function(d) {
var o = {x: sourceNode.x0, y: sourceNode.y0};
return diagonal({source: o, target: o});
可以在此示例中找到更多信息,该示例似乎实现了您想要的内容: https://bl.ocks.org/mbostock/4339184
它使用:
.attr("d", d3.linkHorizontal()
.x(function(d) { return d.y; })
.y(function(d) { return d.x; }));
链接功能是相关的,但不等同于对角线功能。