如何使用D3.js根据链接类型高亮/淡化完整依赖链
解决方案
需修改两处代码即可实现需求:
1. 修复初始化语法错误
原代码中容器类名未加引号,会抛出变量未定义异常,修改为:
var linksContainer = svg.append("g").attr("class", "linksContainer") var nodesContainer = svg.append("g").attr("class", "nodesContainer")
2. 替换mouseEnter事件逻辑为BFS遍历依赖链
原逻辑仅查询当前节点的直接关联关系,改为广度优先搜索遍历所有need类型的有向依赖:
function mouseEnter(event, d) { const selNodes = node.selectAll("circle") const selLink = link const selLinkLabel = linkLabels const selText = node.selectAll("text") const related = [] const relatedLinks = [] const allLinks = force.force('link').links() // 初始化遍历队列 const traverseQueue = [d] related.push(d) // 遍历所有need类型的下游依赖 while(traverseQueue.length) { const current = traverseQueue.shift() allLinks.forEach(link => { // 仅匹配当前节点作为依赖方、类型为need的边 if(link.source.id === current.id && link.type === 'need') { relatedLinks.push(link) const targetNode = link.target // 避免重复添加节点导致循环遍历 if(related.findIndex(item => item.id === targetNode.id) === -1) { related.push(targetNode) traverseQueue.push(targetNode) } } }) } // 统一设置元素状态 selNodes.classed('faded', true) selNodes.filter(dNodes => related.findIndex(n => n.id === dNodes.id) > -1).classed('highlight', true) selLink.classed('faded', true) selLink.filter(dLink => relatedLinks.includes(dLink)).classed('highlight', true) selLinkLabel.classed('faded', true) selLinkLabel.filter((_, idx) => relatedLinks.includes(allLinks[idx])).classed('highlight', true) selText.classed('faded', true) selText.filter(dText => related.findIndex(n => n.id === dText.id) > -1).classed('highlight', true) force.alphaTarget(0.0001).restart() }
修改完成后,悬停car节点时,会自动遍历所有need类型的依赖链,依次高亮car→wheels→tires→rubber,radio因属于use类型不会被高亮,完全符合预期效果。
内容的提问来源于stack exchange,提问作者ICoded
相关产品推荐
相关产品推荐

