在Angular+D3.js应用中如何根据id勾选指定节点及其所有后代节点
问题背景
我正在开发一款使用D3的Angular应用,使用的树形结构数据和节点样式如下:
const treeData = { "id": 1, "name": "Root", "checked": false, "color": "white", "children": [ { "id": 2, "name": "Leaf A", "checked": false, "color": "red", "children": [ { "id": 3, "name": "A - 1", "checked": false, "color": "brown", }, { "id": 4, "name": "A - 2", "checked": false, "color": "orange", }, { "id": 5, "name": "A - 3", "checked": false, "color": "yellow", }, ] }, { "id": 6, "name": "Leaf B", "checked": false, "color": "green", "children": [ { "id": 7, "name": "B - 1", "checked": false, "color": "#00ff40", }, { "id": 8, "name": "B - 2", "checked": false, "color": "#00ff80", } ] } ] };
.node { cursor: pointer; } .node circle { fill: #fff; stroke: #C0C0C0; stroke-width: 1.5px; } .node text { font: 10px sans-serif; } .link { fill: none; stroke: #C0C0C0; stroke-width: 1.5px; }
需求说明
我会从API获取一个id值,该id会匹配上述数据中存在的任意节点id,需要将该匹配节点、其所有子节点及子孙节点都设置为选中状态,请问该如何实现?
实现方案
1. 编写递归处理函数
通过两次递归操作即可完成需求:第一次遍历整棵树找到对应id的目标节点,第二次遍历目标节点的所有后代,将所有节点的checked属性设为true。
// 递归将目标节点及其所有后代的checked属性设为true function setCheckedForNodeAndDescendants(node) { node.checked = true; if (Array.isArray(node.children) && node.children.length) { node.children.forEach(child => setCheckedForNodeAndDescendants(child)); } } // 递归遍历树查找指定id的节点 function findNodeById(root, targetId) { if (root.id === targetId) return root; if (Array.isArray(root.children) && root.children.length) { for (const child of root.children) { const matchedNode = findNodeById(child, targetId); if (matchedNode) return matchedNode; } } return null; } // 调用示例,假设从API获取到的目标id为2 const apiTargetId = 2; const matchedNode = findNodeById(treeData, apiTargetId); if (matchedNode) { setCheckedForNodeAndDescendants(matchedNode); // 此处调用你的D3树重绘方法,更新视图上的节点选中状态 }
2. 更新D3视图
修改你的节点渲染逻辑,将节点样式和checked属性绑定,更新数据后重新触发D3渲染即可看到选中效果,示例绑定逻辑如下:
// 绘制节点圆形部分的逻辑调整 node.append('circle') .attr('r', 8) .style('fill', d => d.checked ? d.color : '#fff') // 选中时填充节点对应颜色,未选中为白色 .style('stroke', '#C0C0C0') .style('stroke-width', '1.5px');
如果是在Angular组件中实现,更新数据后如果视图没有自动刷新,可以注入ChangeDetectorRef调用detectChanges()手动触发变更检测。
内容的提问来源于stack exchange,提问作者user15993695
相关产品推荐
相关产品推荐

