如何在D3.js中按给定坐标设置并固定网络图节点位置?
修复D3.js v3力导向图节点坐标失效与边不显示问题
以下是调整后的完整代码,可直接运行解决节点坐标不生效、边未显示的问题:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>D3.js v3 Fixed Position Force Graph</title> <script src="https://d3js.org/d3.v3.min.js"></script> <style> .node { stroke: #fff; stroke-width: 1.5px; } .link { stroke: #999; stroke-opacity: 0.6; } .label { font-size: 12px; fill: #333; } </style> </head> <body> <svg width="600" height="400"></svg> <script> // 原始节点数据 var rawNodes = [ { "data": { "id": 1, "desc": "Rohit", "pos": [121.0284957885742, 116.3165512084961, 59.36788940429688] } }, { "data": { "id": 2, "desc": "Deep", "pos": [12.10284957885742, 116.3165512084961, 5.936788940429688] } }, { "data": { "id": 3, "desc": "Deepa", "pos": [12.10284957885742, 11.63165512084961, 5.936788940429688] } } ]; // 原始边数据 var rawEdges = [ { "data": { "id": "1_2", "source": 1, "target": 2 } } ]; // 预处理节点:转换为D3力布局兼容格式,锁定坐标 var nodes = rawNodes.map(function(item) { return { id: item.data.id, desc: item.data.desc, x: item.data.pos[0], // 取三维坐标的X轴值 y: item.data.pos[1], // 取三维坐标的Y轴值 fixed: true // 固定节点位置,禁止力布局修改 }; }); // 预处理边:将source/target从ID转为节点对象引用 var edges = rawEdges.map(function(item) { return { id: item.data.id, source: nodes.find(node => node.id === item.data.source), target: nodes.find(node => node.id === item.data.target) }; }); // 初始化SVG容器 var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"); // 创建力布局实例 var force = d3.layout.force() .nodes(nodes) .links(edges) .size([width, height]) .charge(-400) // 可根据需求调整节点排斥力 .linkDistance(100) .on("tick", updateGraph); // 绘制边 var link = svg.selectAll(".link") .data(edges) .enter().append("line") .attr("class", "link"); // 绘制节点 var node = svg.selectAll(".node") .data(nodes) .enter().append("circle") .attr("class", "node") .attr("r", 10) .style("fill", "#3388ff") .call(force.drag); // 保留拖拽功能,不需要可删除此行 // 绘制节点标签 var label = svg.selectAll(".label") .data(nodes) .enter().append("text") .attr("class", "label") .text(function(d) { return d.desc; }); // 启动力布局 force.start(); // 力布局更新回调:同步节点与边的位置 function updateGraph() { // 更新边的端点位置 link .attr("x1", d => d.source.x) .attr("y1", d => d.source.y) .attr("x2", d => d.target.x) .attr("y2", d => d.target.y); // 更新节点位置 node .attr("cx", d => d.x) .attr("cy", d => d.y); // 更新标签位置 label .attr("x", d => d.x + 15) .attr("y", d => d.y + 5); } </script> </body> </html>
核心调整说明
- 节点坐标处理:从原始数据的
data.pos中提取XY坐标,赋值给节点的x/y属性,并设置fixed: true锁定位置,避免力布局的物理模拟改变预设坐标。 - 边数据修正:D3.js v3要求边的
source和target必须是节点对象而非ID,因此通过find方法将ID转换为对应的节点引用。 - 渲染逻辑优化:在力布局的
tick回调中直接使用节点的预设坐标更新元素位置,确保坐标始终与给定值一致。
内容的提问来源于stack exchange,提问作者Rohit Chakraborty
相关产品推荐
相关产品推荐

