D3.js点击两个节点时动态添加连线

如果已经选择了一个节点(firstNode不为null),则将新节点(d)与已选择的节点(firstNode)连接。
将新连线的数据添加到linkData数组中。
重启力模拟以更新图形。
更新连线数据:

使用join方法来更新连线。join方法结合了enter、update和exit三个操作,使得您可以同时处理新添加的元素、更新现有元素和移除不再需要的元素。
箭头标记:

attr(“marker-end”, “url(#arrow)”)将箭头标记应用到每个连线的末端。
可能的改进
确保箭头标记已定义:
在使用marker-end之前,确保您已经在SVG中定义了箭头标记。
javascript
const defs = svg.append(“defs”);
defs.append(“marker”)
.attr(“id”, “arrow”)
.attr(“markerUnits”, “strokeWidth”)
.attr(“markerWidth”, 6)
.attr(“markerHeight”, 6)
.attr(“viewBox”, “0 -3 6 6”)
.append(“path”)
.attr(“d”, “M0,-3L6,0L0,3”)
.attr(“fill”, “#999”);
确保link选择集已初始化:
在您的代码中,link选择集应该在添加连线之前初始化。
javascript
var link = svg.append(“g”)
.attr(“class”, “links”)
.selectAll(“line”);
在tick事件中更新连线位置:
确保在力模拟的tick事件中更新连线的位置。
javascript
simulation.on(“tick”, function() {
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);
});
处理连线数据的id属性:
确保您的节点数据中包含id属性,并且在添加连线时使用这些id。
完整的代码示例
结合上述改进,以下是完整的代码示例:

javascript
// 初始化SVG和力模拟
var svg = d3.select(“body”).append(“svg”)
.attr(“width”, 600)
.attr(“height”, 400);

var simulation = d3.forceSimulation(nodes)
.force(“link”, d3.forceLink().id(function(d) { return d.id; }))
.force(“charge”, d3.forceManyBody())
.force(“center”, d3.forceCenter(300, 200));

// 定义箭头标记
var defs = svg.append(“defs”);
defs.append(“marker”)
.attr(“id”, “arrow”)
.attr(“markerUnits”, “strokeWidth”)
.attr(“markerWidth”, 6)
.attr(“markerHeight”, 6)
.attr(“viewBox”, “0 -3 6 6”)
.append(“path”)
.attr(“d”, “M0,-3L6,0L0,3”)
.attr(“fill”, “#999”);

// 初始化连线选择集
var link = svg.append(“g”)
.attr(“class”, “links”)
.selectAll(“line”);

// 更新力模拟的节点和连线位置
simulation.on(“tick”, function() {
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);
});

// 节点点击事件,添加连线
var firstNode = null;
node.on(“click”, function(event, d) {
if (firstNode) {
// 添加连线
linkData.push({ source: firstNode.id, target: d.id });
console.log(linkData, “linkdata31113”);
simulation.force(“link”).links(linkData);
simulation.alpha(1).restart(); // 重启力模拟
// 更新连线数据绑定
link = link.data(linkData).join(
enter => enter.append(“line”)
.attr(“stroke”, “#999”)
.attr(“stroke-width”, 2)
.attr(“marker-end”, “url(#arrow)”),
update => update, // 更新现有元素
exit => exit.remove() // 移除多余的元素
);
firstNode = null;
} else {
firstNode = d;
}
});
这段代码确保了在点击两个节点时动态添加连线,并且箭头标记正确配置,使得箭头只显示在连线的末端。

以上就是文章全部内容了,如果喜欢这篇文章的话,还希望三连支持一下,感谢!

### D3.js 实现连线与文字的功能 在 D3.js 中实现连线以及在线条旁边显示文字是一个常见的需求,尤其是在绘制树状结构、网络图或其他复杂图形。以下是关于如何通过 D3.js 创建带有文字标注的连线的具体方法。 #### 力导向图中的动态连线 可以利用 `d3.forceSimulation` 来创建力导向图,并在其基础上动态添加连线。当用户点击两个节点,可以通过更新数据集来动态调整连接关系并重新渲染图表[^1]。 ```javascript // 定义初始节点和链接数组 var nodes = [{id: "A"}, {id: "B"}]; var links = []; // 更新函数用于刷新 SVG 上的内容 function update() { var link = svg.selectAll(".link") .data(links, function(d) { return d.source.id + "-" + d.target.id; }); // 添加新的连线 link.enter().append("line") .attr("class", "link"); // 移除旧的连线 link.exit().remove(); var node = svg.selectAll(".node") .data(nodes, function(d) { return d.id; }) .enter().append("circle") .attr("class", "node") .attr("r", 5) .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended)); // 处理拖拽事件逻辑... } // 用户交互处理 (例如鼠标点击事件) svg.on('click', function(event) { const clickedNode = d3.select(this).datum(); if (!clickedNode || !lastClickedNode) return; // 如果两次点击不同,则建立新连线 if (clickedNode !== lastClickedNode && lastClickedNode) { links.push({source: lastClickedNode, target: clickedNode}); update(); // 刷新视图 } }); update(); // 初始化绘图 ``` 上述代码展示了如何监听用户的点击操作并将选中的节点作为源或目标端点构建一条边。 #### 带有路径文字的树形图 对于更复杂的场景比如树形图,在每段连线上加上描述性的标签能够显著提升可读性和用户体验。下面提供了一个简单的例子说明如何做到这一点: ```javascript // 绘制弧线样式的曲线 var diagonal = d3.linkHorizontal() .x(function(d) { return d.y; }) .y(function(d) { return d.x; }); // 遍历所有的 edges 并附加文本标记到它们上面去 edges.each(function(edgeData){ let pathElement = d3.select(this); // 计算中间位置放置 label 的坐标 let midpointX = (edgeData.source.x + edgeData.target.x)/2; let midpointY = (edgeData.source.y + edgeData.target.y)/2; svg.append("text") .attr("transform", `translate(${midpointX},${midpointY})`) .text(() => `${edgeData.label}`); }); ``` 此片段定义了一种水平方向上的弯曲线条样式,并计算出该线条中心的位置以便于我们能在那里写入相应的注释信息[^2]。 #### 总结 以上介绍了两种不同的方式来增强D3可视化效果——一种是在力引导布局下支持实新增删除边;另一种则专注于改进传统层次型拓扑结构的表现形式使其更加直观易懂。两者都涉及到了核心概念即绑定DOM元素至JSON对象集合之上并通过修改这些关联的数据触发重绘过程从而达到预期目的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小纯洁w

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值