繁体   English   中英

D3 mousedown事件删除错误的节点

[英]D3 mousedown event deleting the wrong node

我正在尝试在此jsfiddle中添加删除节点功能

refresh方法是on("mousedown", mousedownNode)每个圆on("mousedown", mousedownNode)添加on("mousedown", mousedownNode)事件,但是当我单击节点GW2它将删除DB节点。 我发现mousedownNode方法删除了正确的节点,但是, node = node.data(nodes); 在刷新方法搞砸了。 我不确定如何解决此问题。

function mousedownNode(d, i) {
 nodes.splice(i, 1);
 links = links.filter(function(l) {
  return l.source !== d && l.target !== d;
 });
 d3.event.stopPropagation();
 refresh();
}

编辑

我有一个将节点名索引到索引映射的映射:

var map = {}
  nodes.forEach(function(d,i){
   map[d.id] = i;
})

links.forEach(function(d) {
   d.source = map[d.source];
   d.target = map[d.target];
})

如您所说,正确的节点将被删除,绑定到<g class="node"></g>也似乎是正确的,但您没有更新节点文本。

这是您所拥有的:

nodeEnter
 .append("text")
 .attr("dx", 12)
 .attr("dy", ".35em")
 .text(function(d) {
  return d.id;
 });

这就是我将其更改为:

nodeEnter
 .append("text")
 .attr("dx", 12)
 .attr("dy", ".35em");

node.select('text')
 .text(function(d) {
  return d.id;
 });

您也可以通过将nodeText分配给这样的变量来更改此变量,例如var nodeText = ...

但这就是要点,当您说删除节点后调用刷新时, exit()选择有效,但现有节点不会自行更新。 希望这是有道理的。 阅读选择内容的工作方式

JSFIDDLE和以下代码段:

编辑:删除可拖动的SVG元素会导致错误。 要解决此问题,请将退出选择行更改为:

node.exit().on('mousedown.drag', null).remove();

在删除元素之前先删除拖动事件绑定。

 rect { fill: none; pointer-events: all; } .node { fill: #000; } .cursor { fill: green; stroke: brown; pointer-events: none; } .link { stroke: #999; } .node text { pointer-events: none; font: 10px sans-serif; } path.link { fill: none; stroke: #666; stroke-width: 1.5px; } 
 <script src="https://d3js.org/d3.v3.min.js"></script> <button id="ref" onclick="refresh()">refresh </button> <script> //setInterval(refresh, 15000); function addNodeCanvas(nodeName,g) { var node = { x: 900, y: 900, id: nodeName, grp:g }; var n = nodes.push(node); console.log(node); refresh(); } function addLinkCanvas(idSrc, idTarget) { if (idSrc != idTarget) { var s = {}, t = {}; nodes.forEach(function(curNode) { if (typeof curNode.id != "undefined") { if (curNode.id == idSrc) { s = curNode; } if (curNode.id == idTarget) { t = curNode; } } }); //console.log( { s,t}); links.push({ source: s, target: t }); }; refresh(); } var fill = d3.scale.category20(); var links = [{ source: "FH", target: "TP" }]; var nodes = [ { id: "FH", x: 100, y: 110 }, { id: "TP", x: 200, y: 110 }, { id: "GW1", x: 200, y: 110 }, { id: "GW", x: 200, y: 110 }, { id: "GW2", x: 200, y: 110 }, { id: "DB", x: 100, y: 110 } ] var width = 600, height = 400, radius = 8; var map = {} nodes.forEach(function(d,i){ map[d.id] = i; }) links.forEach(function(d) { d.source = map[d.source]; d.target = map[d.target]; }) var force = d3.layout .force() .size([width, height]) .nodes(nodes) .links(links) .linkDistance(50) .charge(-100) .on("tick", tick); var svg = d3 .select("body") .append("svg") .attr("width", width) .attr("height", height); // build the arrow. var arrows = svg .append("svg:defs") .selectAll("marker") .data(["arrow"]) // Different link/path types can be defined here .enter() .append("svg:marker") // This section adds in the arrows .attr("id", String) .attr("viewBox", "0 -5 10 10") .attr("refX", 10) .attr("refY", -1) .attr("markerWidth", 4) .attr("markerHeight", 4) .attr("orient", "auto") .append("svg:path") .attr("d", "M0,-5L10,0L0,5"); svg .append("rect") .attr("width", width) .attr("height", height); var nodes = force.nodes(), links = force.links(), node = svg.selectAll(".node"), link = svg.selectAll(".link"); function tick() { link.attr("d", function(d) { var dx = d.target.x - d.source.x, dy = d.target.y - d.source.y; var angle = Math.atan2(dy, dx); var offsetX = radius * Math.cos(angle); var offsetY = radius * Math.sin(angle); dr = Math.sqrt(dx * dx + dy * dy); return ( "M" + (d.source.x + offsetX) + "," + (d.source.y + offsetY) + "A" + dr + "," + dr + " 0 0,1 " + (d.target.x - offsetX) + "," + (d.target.y - offsetY) ); }); node.attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); } function mousedownNode(d, i) { nodes.splice(i, 1); links = links.filter(function(l) { return l.source !== d && l.target !== d; }); d3.event.stopPropagation(); refresh(); } refresh(); function refresh() { link = link.data(links); link .enter() .append("path") .attr("class", "link") .attr("marker-end", "url(#arrow)"); link.exit().remove(); node = node.data(nodes); var nodeEnter = node .enter() .insert("g") .attr("class", "node") .on("mousedown", mousedownNode) .call(force.drag); nodeEnter .append("image") .attr("xlink:href", "https://github.com/favicon.ico") .attr("x", -8) .attr("y", -8) .attr("width", 16) .attr("height", 16); nodeEnter .append("text") .attr("dx", 12) .attr("dy", ".35em"); node.select('text') .text(function(d) { return d.id; }); node.exit().on('mousedown.drag', null).remove(); force.start(); } </script> 

我没有深入研究,因为我觉得问题对我来说很明显。 我无法确切解释GW节点为何返回,但是我认为这与您的数据绑定不正确有关。

当您进行数据连接时,您基本上是在告诉D3键入索引。 现在,如果不是索引中的最后一个GW ,则将重新使用DOM中的原始GW节点,因为索引将偏移1。

node = node.data(nodes);

如果您将此更改为输入字段

node = node.data(nodes, d => d.id);

您会发现问题消失了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM