3d-force-graph双向边优化:合并双向链接为双箭头单边
解决3d-force-graph双向边合并为双箭头单链接的问题
步骤1:预处理图数据,合并双向边
先把成对的A→B和B→A边合并为一条带标记的边,消除数据冗余。通过生成统一的边键(将两个节点ID按升序拼接)来识别双向边:
function mergeBidirectionalEdges(graphData) { const edgeMap = new Map(); const { nodes, links } = graphData; links.forEach(link => { // 生成统一边键,确保A-B和B-A对应同一个标识 const edgeKey = [link.source, link.target].sort((a, b) => { // 兼容节点对象或纯ID的情况 const idA = typeof a === 'object' ? a.id : a; const idB = typeof b === 'object' ? b.id : b; return idA.localeCompare(idB); }).join('-'); if (!edgeMap.has(edgeKey)) { edgeMap.set(edgeKey, { ...link, bidirectional: false }); } else { // 标记该边为双向 edgeMap.get(edgeKey).bidirectional = true; } }); return { nodes, links: Array.from(edgeMap.values()) }; } // 处理原始图数据 const mergedData = mergeBidirectionalEdges(gData);
步骤2:自定义链接的双箭头渲染
利用库的linkThreeObjectExtend配置,给标记为双向的边添加反向箭头,实现单条边带双箭头的视觉效果:
const Graph = ForceGraph3D() (document.getElementById('3d-graph')) .graphData(mergedData) .linkDirectionalArrowLength(3.5) .linkDirectionalArrowRelPos(1) .linkCurvature(0) // 合并后使用直边 .linkThreeObjectExtend(true) // 允许扩展链接的3D对象 .linkThreeObject(link => { if (link.bidirectional) { // 创建反向箭头几何体 const reverseArrow = new THREE.Mesh( new THREE.ConeGeometry(0.5, 3.5, 8), new THREE.MeshBasicMaterial({ color: link.color || '#aaa' }) ); reverseArrow.position.set(-1, 0, 0); // 定位到链接起点 reverseArrow.rotation.set(Math.PI, 0, 0); // 反转箭头朝向 return reverseArrow; } return null; });
补充说明
- 数据合并后,原本的两条双向边变为一条,减少了大型图的数据量,同时提升渲染性能。
- 若需要调整箭头样式,可修改
ConeGeometry的尺寸参数或MeshBasicMaterial的颜色、材质属性。
内容的提问来源于stack exchange,提问作者SanjiSqurt
相关产品推荐
相关产品推荐

