D3 mousedown事件删除错误的节点 [英] D3 mousedown event deleting the wrong node

查看:62
本文介绍了D3 mousedown事件删除错误的节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在此 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆