📅  最后修改于: 2023-12-03 15:00:18.678000             🧑  作者: Mango
在 D3.js 中,每个节点(node)都有一个父节点(parent)属性,用于表示节点在树形结构中的位置关系。node.parent 属性可以方便地获取当前节点的父节点,并可以通过它进一步遍历整个树形结构。
获取当前节点的父节点很简单,只需要使用 node.parent 即可。例如,可以使用以下代码获取当前节点的父节点:
const parent = node.parent;
通过 node.parent 属性,可以方便地遍历整个树形结构。例如,可以使用以下代码遍历整个树形结构并输出每个节点的深度和名称:
function visit(node, depth) {
console.log(' '.repeat(depth) + node.name);
if (node.children) {
node.children.forEach(child => {
visit(child, depth + 1);
});
}
}
visit(root, 0);
在上面的代码中,我们定义了一个 visit 函数,用于遍历树形结构。函数接受两个参数,一个是当前节点(node),另一个是当前节点的深度(depth)。首先,我们使用 console.log 输出当前节点的名称,其中使用了 ' '.repeat(depth) 来表示当前节点的深度。然后,我们判断当前节点是否有子节点,如果有,就依次遍历每个子节点,并将当前深度加一传入子节点的 visit 函数中。
以下是一个完整的示例代码,用于渲染一个简单的树形结构。在代码中,我们使用了一个 TreeLayout 实例来指定树形结构的布局,然后使用了一个 HierarchicalDataSource 来指定树形结构的数据源。我们可以通过点击每个节点来切换其展开/收起状态。
const data = {
name: 'root',
children: [
{
name: 'node 1',
children: [
{
name: 'node 1.1'
},
{
name: 'node 1.2'
}
]
},
{
name: 'node 2'
}
]
};
const treeLayout = d3.tree().size([400, 300]);
const dataSource = new d3.HierarchicalDataSource(data);
const root = d3.hierarchy(data, d => d.children);
// 创建 SVG 元素
const svg = d3.select('body')
.append('svg')
.attr('width', 400)
.attr('height', 300);
// 绘制树形结构
const nodes = treeLayout(root);
svg.selectAll('g.node')
.data(nodes.descendants())
.enter()
.append('g')
.attr('class', 'node')
.attr('transform', d => `translate(${d.x},${d.y})`)
.append('circle')
.attr('r', 5)
.on('click', d => {
if (d.children) {
d.children = null;
} else {
d.children = d.data.children;
}
nodeUpdate(d);
});
svg.selectAll('path.link')
.data(nodes.links())
.enter()
.append('path')
.attr('class', 'link')
.attr('d', d3.linkHorizontal()
.x(d => d.x)
.y(d => d.y))
.attr('stroke', '#999')
.attr('stroke-width', '1')
.attr('fill', 'none');
// 更新节点
function nodeUpdate(node) {
const nodes = treeLayout(root);
const nodeGroup = svg.selectAll('g.node')
.data(nodes.descendants())
.enter()
.append('g')
.attr('class', 'node')
.attr('transform', d => `translate(${d.x},${d.y})`)
.on('click', d => {
if (d.children) {
d.children = null;
} else {
d.children = d.data.children;
}
nodeUpdate(d);
});
nodeGroup.append('circle')
.attr('r', 5)
.attr('stroke', '#333')
.attr('fill', '#fff');
nodeGroup.append('text')
.text(d => d.data.name)
.attr('dx', 10)
.attr('dy', 5);
}