// 边样式统一配置 // 所有边类型及颜色 export const edgeTypeColors = { '属于': '#9b59b6', '包含': '#3498db', '标签共现': '#2ecc71', '分类共现': '#f39c12', '匹配': '#e94560', '推导': '#00bcd4', // 青色 - 推导关系 '组成': '#8bc34a', // 浅绿色 - 组合成员 '支撑': '#ff9800', // 橙色 - 支撑关系 '关联': '#9c27b0' // 紫色 - 关联关系 } // 获取边样式(统一入口) // edge: { type, score, ... } export function getEdgeStyle(edge) { const type = edge.type || '' const score = edge.score const color = edgeTypeColors[type] || '#666' // 匹配边:>=0.8 实线,否则虚线 let strokeDasharray = 'none' if (type === '匹配') { strokeDasharray = (score >= 0.8) ? 'none' : '4,2' } // 推导边:使用箭头,根据分数调整透明度 // 组成边:实线样式(和推导边一样) // 不同边类型的透明度计算 let opacity = 0.3 if (type === '匹配') { opacity = Math.max(0.3, score * 0.7) } else if (type === '推导') { opacity = Math.max(0.4, score * 0.8) } else if (type === '组成') { opacity = 0.6 } else if (type === '支撑') { opacity = 0.7 } else if (type === '关联') { opacity = 0.6 } // 关联边使用虚线 if (type === '关联') { strokeDasharray = '4,2' } // 箭头配置 const hasArrow = ['推导', '支撑'].includes(type) const arrowSize = type === '推导' ? 8 : 6 const arrowRefX = type === '推导' ? 20 : 15 return { color, strokeWidth: type === '推导' ? 2 : 1.5, strokeDasharray, opacity, hasArrow, arrowSize, arrowRefX, markerId: hasArrow ? `arrow-${type}` : null, scoreText: score !== undefined ? score.toFixed(2) : '' } } // 创建箭头标记定义(供 SVG defs 使用) export function createArrowMarkers(defs) { const arrowTypes = ['推导', '支撑'] arrowTypes.forEach(type => { const style = getEdgeStyle({ type, score: 1 }) // 正常箭头 defs.append('marker') .attr('id', `arrow-${type}`) .attr('viewBox', '0 -5 10 10') .attr('refX', style.arrowRefX) .attr('refY', 0) .attr('markerWidth', style.arrowSize) .attr('markerHeight', style.arrowSize) .attr('orient', 'auto') .append('path') .attr('d', 'M0,-5L10,0L0,5') .attr('fill', style.color) // 置灰箭头(用于 hover 时其他边) defs.append('marker') .attr('id', `arrow-${type}-dimmed`) .attr('viewBox', '0 -5 10 10') .attr('refX', style.arrowRefX) .attr('refY', 0) .attr('markerWidth', style.arrowSize) .attr('markerHeight', style.arrowSize) .attr('orient', 'auto') .append('path') .attr('d', 'M0,-5L10,0L0,5') .attr('fill', style.color) .attr('fill-opacity', 0.15) }) }