Svg 使用d3js,我如何使用树布局在父节点中直观地放置子节点?
我正在尝试使用d3js来绘制各个位置的服务器图。下面是输入数据的一个示例提取Svg 使用d3js,我如何使用树布局在父节点中直观地放置子节点?,svg,d3.js,Svg,D3.js,我正在尝试使用d3js来绘制各个位置的服务器图。下面是输入数据的一个示例提取 {"type": "customer", "name": "Acme", "children": [ { "type": "site", "name": "Wichita", "children": [ { "type": "server", "name": "server1"
{"type": "customer", "name": "Acme", "children": [
{
"type": "site",
"name": "Wichita",
"children": [
{
"type": "server",
"name": "server1"
},
{
"type": "server",
"name": "server2"
}
]
},
{
"type": "site",
"name": "Springfield",
"children": [
{
"type": "server",
"name": "server1"
},
{
"type": "server",
"name": "server2"
},
{
"type": "server",
"name": "server3"
}
]
}
]}
这些站点将有不同数量的服务器。每个服务器都应该是代表站点的矩形中的一个矩形。
我可以分别创建站点和服务器矩形,但我想我希望服务器节点绑定在其父站点的矩形下
节点进行适当的分组,特别是我们以后将svg导入Visio时。输入json位于var treeData中。还有,我
在正确定位时遇到困难,通过适当的分组可能会更容易
var viz = d3.select("#viz").append("svg:svg")
.attr("width", 1200)
.attr("height", layoutHeight)
.append("svg:g");
var tree = d3.layout.tree().size([layoutHeight, 300]);
var nodes = tree.nodes(treeData);
viz.append("svg:text")
.attr("dx", "0")
.attr("dy", 20)
.attr("font-size", 24)
.attr("text-anchor", "start")
.text(json.customerName);
var siteNodes = viz.selectAll("g.node")
.data(nodes)
.enter().append("svg:g")
.filter(function(d) { return d.type === "site" })
.attr("transform", function(d) { return "translate(" + d.y + "," + (d.x * 1.5 - (d.children.length * serverHeight * 1.1 / 2)) + ")"; });
siteNodes.append("svg:rect")
.attr("width", 300)
.attr("height", function(d) { return serverHeight * (d.children.length + 1); })
.attr("stroke", "black")
.attr("stroke-width", "1")
.attr("fill", "white");
var serverNodes = viz.selectAll("g.node")
.data(nodes)
.enter().append("svg:g")
.filter(function(d) { return d.type === "server" })
.attr("transform", function(d) { return "translate(" + (d.y - 125) + "," + d.x + ")"; });
serverNodes.append("svg:rect")
.attr("width", 250)
.attr("height", serverHeight)
.attr("font-size", 10)
.attr("stroke", "black")
.attr("stroke-width", "1")
.attr("fill-opacity", "0.1")
.attr("fill", "blue");
我是d3js新手,我怀疑一个主要因素是我还没有以正确的方式思考d3js。由于您没有提供完整的代码,我不得不对值进行一些假设。我所做的改变应该很容易理解。是帮助你摆脱困境的小提琴。我不清楚您在站点上使用的转换,我给出了一个近似值来让您继续。你肯定需要调整它。希望这有帮助
.attr("transform", function(d) { return "translate(" + (d.y) + "," + (d.x * 1.25 - (d.children.length * serverHeight * 0.9)) + ")"; });
以下是我在和的帮助下制定的解决方案: 我更改了数据中的一些字段名,使其看起来更像:
var treeData = {type: "customer", name: "Acme", children: [
{type: "site", name: "Wichita", servers: [
{type: "server", name: "server1", status: "Powered On"},
{type: "server", name: "server2", status: "Powered On"}]},
{type: "site", name: "Springfield", servers: [
{type: "server", name: "server1", status: "Powered On"},
{type: "server", name: "server2", status: "Powered On"},
{type: "server", name: "server3", status: "Powered On"}]
}
]};
计算布局所需的空间:
var serverHeight = 50;
var serverWidth = 250;
var siteWidth = serverWidth + 50;
var layoutVerticalOffset = 20;
var layoutHeight = 150 + (maxServerCount + 2) * serverHeight * 1.5;
var layoutWidth = treeData.children.length * siteWidth * 1.5;
var viz = d3.select("#viz").append("svg:svg")
.attr("height", layoutHeight)
.attr("width", layoutWidth + siteWidth)
.append("svg:g");
var tree = d3.layout.tree().size([layoutWidth, 0]);
我向站点节点添加了一个类:
var siteNodes = viz.selectAll("g.node")
.data(nodes)
.enter().append("svg:g")
.filter(function(d) { return d.type === "site" })
.attr("class", "site")
.attr("transform", function(d) {
return "translate(" + d.x + "," + 100 + ")";
});
<g class="site" transform="translate(300,35)">
<rect width="300" height="165" stroke="black" stroke-width="1" fill="white"/>
<text dx="0" dy="12" font-size="18" text-anchor="end">Site</text>
<text dx="0" dy="34" font-size="18" text-anchor="end">Wichita</text>
<g class="server" transform="translate(25,25)">
<rect width="250" height="50" font-size="10" stroke="black" stroke-width="1" fill-opacity="0.1" fill="blue"/>
</g>
<g class="server" transform="translate(25,100)">
<rect width="250" height="50" font-size="10" stroke="black" stroke-width="1" fill-opacity="0.1" fill="blue"/>
</g>
</g>
并在构建服务器节点时使用该类进行选择:
var serverNodes = siteNodes.selectAll(".site")
.data(function(d) { return d.servers; })
.enter().append("svg:g")
.attr("class", "server")
.attr("transform", function(d, i) {
return "translate(" + 25 + "," + (serverHeight / 2 + i * serverHeight * 1.5) + ")";
});
结果是服务器由正确嵌套在站点节点中的g节点表示:
var siteNodes = viz.selectAll("g.node")
.data(nodes)
.enter().append("svg:g")
.filter(function(d) { return d.type === "site" })
.attr("class", "site")
.attr("transform", function(d) {
return "translate(" + d.x + "," + 100 + ")";
});
<g class="site" transform="translate(300,35)">
<rect width="300" height="165" stroke="black" stroke-width="1" fill="white"/>
<text dx="0" dy="12" font-size="18" text-anchor="end">Site</text>
<text dx="0" dy="34" font-size="18" text-anchor="end">Wichita</text>
<g class="server" transform="translate(25,25)">
<rect width="250" height="50" font-size="10" stroke="black" stroke-width="1" fill-opacity="0.1" fill="blue"/>
</g>
<g class="server" transform="translate(25,100)">
<rect width="250" height="50" font-size="10" stroke="black" stroke-width="1" fill-opacity="0.1" fill="blue"/>
</g>
</g>
场地
威奇托
这将形成适当的分组,这对导出非常重要,并通过使服务器图形与站点图形相对,简化了服务器图形的计算
谢谢您的回答,对于丢失的部分,我深表歉意。我在思考如何将子节点绑定到父节点。如果不是这样,我可以调整值,直到它们一致工作。在每个节点上由填充的属性之一是对父节点的引用。好的,我真正谈论的是发生在serverNodes.append()上的图形绑定,而不是发生在var nodes=tree.nodes(treeData);。