点击Graph边缘+-图标,如何实现Node显隐及Edges数据同步更新
实现Graph节点显隐切换与边同步更新方案
背景说明
现有Graph包含两类节点:
- 可隐藏节点:
is_hiddenable为true,通过hidden属性控制是否隐藏; - 不可隐藏节点:
is_hiddenable为false。
节点间的连接为Edges,当Edges的icon属性为'-'或'+'时,点击可触发节点显隐操作。
示例数据结构
节点数据
let nodes = [ { id: 1, node_name: "Node-1", is_hiddenable: false, hidden: false }, { id: 2, node_name: "Node-2", is_hiddenable: false, hidden: false }, { id: 3, node_name: "Node-3", is_hiddenable: true, hidden: false }, // 可扩展至任意数量节点 ];
边数据
let edges = [ { from: 1, to: 2, icon: "" }, { from: 2, to: 3, icon: "-" }, // 可扩展至任意数量边 ];
核心操作逻辑
- 点击
'-'图标(如Node-7到Node-8的边):隐藏该边后续串联的所有可隐藏节点(如Node-8、9、10),同时更新Edges——将原末端节点的连接(如{ from: 10, to: 11, icon: "" })改为从触发节点直接连接到末端不可隐藏节点({ from: 7, to: 11, icon: "" }),并将原触发边的icon改为'+'。 - 点击
'+'图标(如Node-7到Node-11的边):显示之前隐藏的对应串联可隐藏节点,恢复原Edges的完整连接,并将触发边的icon改回'-'。
实现函数
下面是完整的JavaScript函数实现,接收点击触发的节点ID(对应边的from节点ID),自动处理节点显隐和边更新:
// 辅助函数:根据from节点ID找到对应的触发边 function getTriggerEdge(fromId) { return edges.find(edge => edge.from === fromId && (edge.icon === '-' || edge.icon === '+')); } // 辅助函数:获取从指定节点开始的串联可隐藏节点链及末端连接 function getHiddenableChain(startNodeId) { const chain = []; let currentId = startNodeId; let endEdge = null; while (true) { // 找到当前节点的出边 const nextEdge = edges.find(edge => edge.from === currentId); if (!nextEdge) break; const nextNode = nodes.find(node => node.id === nextEdge.to); if (!nextNode) break; // 若下一个节点是可隐藏的,加入链 if (nextNode.is_hiddenable) { chain.push(nextNode); currentId = nextNode.id; } else { // 遇到不可隐藏节点,记录其连接边并终止 endEdge = nextEdge; break; } } return { chain, endEdge }; } // 主函数:处理节点显隐切换与边更新 function toggleNodeVisibility(triggerFromId) { const triggerEdge = getTriggerEdge(triggerFromId); if (!triggerEdge) return; const isHideAction = triggerEdge.icon === '-'; const { chain, endEdge } = getHiddenableChain(triggerFromId); if (isHideAction) { // 执行隐藏操作:隐藏所有可隐藏节点 chain.forEach(node => { node.hidden = true; }); // 更新边:移除原链中的所有边,将触发节点直接连到末端节点 edges = edges.filter(edge => !chain.some(node => edge.from === node.id)); if (endEdge) { edges.push({ from: triggerFromId, to: endEdge.to, icon: "" }); } // 将触发边的图标改为+ triggerEdge.icon = '+'; } else { // 执行显示操作:显示所有可隐藏节点 chain.forEach(node => { node.hidden = false; }); // 恢复原边:移除触发节点到末端的直接边,重新添加链中的边 edges = edges.filter(edge => !(edge.from === triggerFromId && endEdge && edge.to === endEdge.to)); // 按顺序添加链中的节点连接边 let prevId = triggerFromId; chain.forEach(node => { edges.push({ from: prevId, to: node.id, icon: "-" }); prevId = node.id; }); // 添加末端节点的连接边 if (endEdge) { edges.push(endEdge); } // 将触发边的图标改回- triggerEdge.icon = '-'; } }
使用说明
调用示例:
// 点击Node-2对应的触发边(icon为'-'),隐藏后续可隐藏节点 toggleNodeVisibility(2); // 再次点击Node-2对应的触发边(此时icon为'+'),恢复显示节点 toggleNodeVisibility(2);
内容的提问来源于stack exchange,提问作者Jayanta Garu
相关产品推荐
相关产品推荐

