特定深度的 d3 集群布局节点未对齐
d3 cluster layout nodes at a particular depth are not aligned
我有以下 JSFiddle 代码:
我希望 node2
和 node3
垂直对齐,因为它们处于相同的深度。
我还希望所有叶节点也对齐。
但是,此代码仅对齐叶节点,其余节点处于不同级别。
最简单的是使用树布局,它将节点对齐depth
,然后将叶节点移动到最大深度的位置。
var root = getData();
var nodes = tree.nodes(root);
var links = tree.links(nodes);
var maxY = d3.max(nodes, d => d.y);
var linkSources = new Set(links.map(d => d.source.name));
nodes.forEach( d => { if (!linkSources.has(d.name)) { d.y = maxY; } });
一个完整的例子:
var width = 500,
height = 500;
var diameter = 300;
var duration = 2000;
var tree = d3.layout.tree()
.size([height, width - 160]);
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(80,0)");
var root = getData();
var nodes = tree.nodes(root);
var links = tree.links(nodes);
var maxY = d3.max(nodes, d => d.y);
var linkSources = new Set(links.map(d => d.source.name));
nodes.forEach( d => { if (!linkSources.has(d.name)) { d.y = maxY; } });
var link = svg.selectAll(".link")
.data(links)
.enter()
.append("path")
.attr("class", "link")
.style("stroke", "#8da0cb")
.attr("d", diagonal);
var node = svg.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function (d) {
return "translate(" + d.y + "," + d.x + ")";
})
node.append("circle")
.attr("r", 4.5);
node.append("text")
.attr("dx", function (d) { return d.children ? -8 : 8; })
.attr("dy", 3)
.style("text-anchor", function (d) { return d.children ? "end" : "start"; })
.text(function (d) { return d.name; });
function getData() {
return {
name: "node1",
id: "1",
children: [
{
name: "node2",
id: "2",
children: [
{
name: "node5",
id: "5",
children: [
{
name: "node6",
id: "6",
children: [
{
name: "node7",
id: "7",
}
]
}
]
}
]
},
{
name: "node3",
id: "3",
children: [
{
name: "node8",
id: "8",
}
]
},
{
name: "node4",
id: "4",
}
]
};
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node {
font: 10px sans-serif;
}
.link {
fill: none;
stroke: tan;
stroke-width: 1.5px;
}
<script type="text/javascript" src="https://d3js.org/d3.v3.js"></script>
现在出现了一个不同的问题。对路径进行排序。这是一个完全不同的球类游戏,因为您必须根据直到叶节点的深度数递归进行。
也可以通过集群布局来完成。
找到每个深度的最小y,如果是源则调整节点的位置
var root = getData(),
nodes = cluster.nodes(root),
links = cluster.links(nodes);
var depthMinY = {};
nodes.forEach( d => { if (!depthMinY[d.depth]) { depthMinY[d.depth] = d.y;}
depthMinY[d.depth] = Math.min(depthMinY[d.depth], d.y);});
var linkSources = new Set(links.map(d => d.source.name));
nodes.forEach( d => { if (linkSources.has(d.name)) { d.y = depthMinY[d.depth]; } });
一个完整的例子:
var width = 500,
height = 500;
var diameter = 300;
var duration = 2000;
var cluster = d3.layout.cluster()
.size([height, width - 160]);
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(80,0)");
var root = getData(),
nodes = cluster.nodes(root),
links = cluster.links(nodes);
var depthMinY = {};
nodes.forEach( d => { if (!depthMinY[d.depth]) { depthMinY[d.depth] = d.y;}
depthMinY[d.depth] = Math.min(depthMinY[d.depth], d.y);});
var linkSources = new Set(links.map(d => d.source.name));
nodes.forEach( d => { if (linkSources.has(d.name)) { d.y = depthMinY[d.depth]; } });
var link = svg.selectAll(".link")
.data(links)
.enter()
.append("path")
.attr("class", "link")
.style("stroke", "#8da0cb")
.attr("d", diagonal);
var node = svg.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function (d) {
return "translate(" + d.y + "," + d.x + ")";
})
node.append("circle")
.attr("r", 4.5);
node.append("text")
.attr("dx", function (d) { return d.children ? -8 : 8; })
.attr("dy", 3)
.style("text-anchor", function (d) { return d.children ? "end" : "start"; })
.text(function (d) { return d.name; });
function getData() {
return {
name: "node1",
id: "1",
children: [
{
name: "node2",
id: "2",
children: [
{
name: "node5",
id: "5",
children: [
{
name: "node6",
id: "6",
children: [
{
name: "node7",
id: "7",
}
]
}
]
}
]
},
{
name: "node3",
id: "3",
children: [
{
name: "node8",
id: "8",
children: [
{
name: "node9",
id: "9",
}
]
}
]
},
{
name: "node4",
id: "4",
}
]
};
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node {
font: 10px sans-serif;
}
.link {
fill: none;
stroke: tan;
stroke-width: 1.5px;
}
<script type="text/javascript" src="https://d3js.org/d3.v3.js"></script>
我有以下 JSFiddle 代码:
我希望 node2
和 node3
垂直对齐,因为它们处于相同的深度。
我还希望所有叶节点也对齐。
但是,此代码仅对齐叶节点,其余节点处于不同级别。
最简单的是使用树布局,它将节点对齐depth
,然后将叶节点移动到最大深度的位置。
var root = getData();
var nodes = tree.nodes(root);
var links = tree.links(nodes);
var maxY = d3.max(nodes, d => d.y);
var linkSources = new Set(links.map(d => d.source.name));
nodes.forEach( d => { if (!linkSources.has(d.name)) { d.y = maxY; } });
一个完整的例子:
var width = 500,
height = 500;
var diameter = 300;
var duration = 2000;
var tree = d3.layout.tree()
.size([height, width - 160]);
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(80,0)");
var root = getData();
var nodes = tree.nodes(root);
var links = tree.links(nodes);
var maxY = d3.max(nodes, d => d.y);
var linkSources = new Set(links.map(d => d.source.name));
nodes.forEach( d => { if (!linkSources.has(d.name)) { d.y = maxY; } });
var link = svg.selectAll(".link")
.data(links)
.enter()
.append("path")
.attr("class", "link")
.style("stroke", "#8da0cb")
.attr("d", diagonal);
var node = svg.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function (d) {
return "translate(" + d.y + "," + d.x + ")";
})
node.append("circle")
.attr("r", 4.5);
node.append("text")
.attr("dx", function (d) { return d.children ? -8 : 8; })
.attr("dy", 3)
.style("text-anchor", function (d) { return d.children ? "end" : "start"; })
.text(function (d) { return d.name; });
function getData() {
return {
name: "node1",
id: "1",
children: [
{
name: "node2",
id: "2",
children: [
{
name: "node5",
id: "5",
children: [
{
name: "node6",
id: "6",
children: [
{
name: "node7",
id: "7",
}
]
}
]
}
]
},
{
name: "node3",
id: "3",
children: [
{
name: "node8",
id: "8",
}
]
},
{
name: "node4",
id: "4",
}
]
};
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node {
font: 10px sans-serif;
}
.link {
fill: none;
stroke: tan;
stroke-width: 1.5px;
}
<script type="text/javascript" src="https://d3js.org/d3.v3.js"></script>
现在出现了一个不同的问题。对路径进行排序。这是一个完全不同的球类游戏,因为您必须根据直到叶节点的深度数递归进行。
也可以通过集群布局来完成。
找到每个深度的最小y,如果是源则调整节点的位置
var root = getData(),
nodes = cluster.nodes(root),
links = cluster.links(nodes);
var depthMinY = {};
nodes.forEach( d => { if (!depthMinY[d.depth]) { depthMinY[d.depth] = d.y;}
depthMinY[d.depth] = Math.min(depthMinY[d.depth], d.y);});
var linkSources = new Set(links.map(d => d.source.name));
nodes.forEach( d => { if (linkSources.has(d.name)) { d.y = depthMinY[d.depth]; } });
一个完整的例子:
var width = 500,
height = 500;
var diameter = 300;
var duration = 2000;
var cluster = d3.layout.cluster()
.size([height, width - 160]);
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(80,0)");
var root = getData(),
nodes = cluster.nodes(root),
links = cluster.links(nodes);
var depthMinY = {};
nodes.forEach( d => { if (!depthMinY[d.depth]) { depthMinY[d.depth] = d.y;}
depthMinY[d.depth] = Math.min(depthMinY[d.depth], d.y);});
var linkSources = new Set(links.map(d => d.source.name));
nodes.forEach( d => { if (linkSources.has(d.name)) { d.y = depthMinY[d.depth]; } });
var link = svg.selectAll(".link")
.data(links)
.enter()
.append("path")
.attr("class", "link")
.style("stroke", "#8da0cb")
.attr("d", diagonal);
var node = svg.selectAll(".node")
.data(nodes)
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function (d) {
return "translate(" + d.y + "," + d.x + ")";
})
node.append("circle")
.attr("r", 4.5);
node.append("text")
.attr("dx", function (d) { return d.children ? -8 : 8; })
.attr("dy", 3)
.style("text-anchor", function (d) { return d.children ? "end" : "start"; })
.text(function (d) { return d.name; });
function getData() {
return {
name: "node1",
id: "1",
children: [
{
name: "node2",
id: "2",
children: [
{
name: "node5",
id: "5",
children: [
{
name: "node6",
id: "6",
children: [
{
name: "node7",
id: "7",
}
]
}
]
}
]
},
{
name: "node3",
id: "3",
children: [
{
name: "node8",
id: "8",
children: [
{
name: "node9",
id: "9",
}
]
}
]
},
{
name: "node4",
id: "4",
}
]
};
}
.node circle {
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node {
font: 10px sans-serif;
}
.link {
fill: none;
stroke: tan;
stroke-width: 1.5px;
}
<script type="text/javascript" src="https://d3js.org/d3.v3.js"></script>