D3 mousedown事件删除错误的节点 [英] D3 mousedown event deleting the wrong node
问题描述
我正在尝试在此 jsfiddle 中添加删除节点功能
I am trying to add a delete node feature in this jsfiddle
刷新
方法是在(mousedown,mousedownNode)事件上添加每个圆圈,但当我点击节点
GW2
时,它会删除 DB
节点。我发现 mousedownNode
方法删除了正确的节点,但刷新中的 node = node.data(nodes);
方法搞乱了。我不知道如何解决这个问题。
The refresh
method is adding on("mousedown", mousedownNode)
event to each circle, but when I click the node GW2
it deletes the DB
node. I figured out that mousedownNode
method deletes the correct node but, node = node.data(nodes);
in the refresh method is messing up. I am not sure how to fix this problem.
function mousedownNode(d, i) {
nodes.splice(i, 1);
links = links.filter(function(l) {
return l.source !== d && l.target !== d;
});
d3.event.stopPropagation();
refresh();
}
编辑
我有一个地图,它将节点名称索引到索引映射:
I have a map which is indexing the node name to index mapping :
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>
也似乎正确但你不是更新节点文本。
As you said, the correct nodes are getting deleted and the data bound to the <g class="node"></g>
also seems correct BUT you're not UPDATING the node texts.
这就是你所拥有的:
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 = ...
You can also change this by assigning the nodeText to a variable like this var nodeText = ...
但是,重要的是,当您在删除节点后调用刷新时, exit()
选择有效但现有节点不能自行更新。希望这是有道理的。阅读选择如何运作
But here's the point, when you call the refresh after say deleting a node, the exit()
selection works BUT the existing nodes DO NOT update by themselves. Hope this makes sense. Read How Selections Work
JSFIDDLE ,这里是片段:
编辑:删除可拖动的SVG元素会导致错误。要解决此问题,请将退出选择行更改为:
node.exit().on('mousedown.drag', null).remove();
在删除元素之前删除了绑定事件。
that removes the drag event bound before removing the element.
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(" + d.x + "," + d.y + ")";
});
}
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>
这篇关于D3 mousedown事件删除错误的节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!