Javascript d3.js删除节点后,强制布局拖动停止工作

Javascript d3.js删除节点后,强制布局拖动停止工作,javascript,d3.js,Javascript,D3.js,我见过,也见过,但它们不起作用。 我的密码是开着的 两个问题: 1.单击节点并按键盘上的“删除”按钮时,节点和相应的链接将被删除,但为什么之后我无法拖动其余节点? 2.我尝试附加图像(使用节点数组中的路径),但图像没有显示。圆圈消失了,没有图像出现(图像的路径是正确的。在同一个程序中,我尝试在屏幕的一角显示图像,结果成功) 代码: <!DOCTYPE html> <meta charset="utf-8"> <style> .background { /*st

我见过,也见过,但它们不起作用。
我的密码是开着的

两个问题:
1.单击节点并按键盘上的“删除”按钮时,节点和相应的链接将被删除,但为什么之后我无法拖动其余节点?
2.我尝试附加图像(使用
节点
数组中的路径),但图像没有显示。圆圈消失了,没有图像出现(图像的路径是正确的。在同一个程序中,我尝试在屏幕的一角显示图像,结果成功)

代码:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.background { /*stroke: gray; stroke-width: 1px; fill: rgb(252,231,216);*/ cursor: move; }
.link { stroke: #000;  stroke-width: 1.5px; }
.node { fill: #ccc;  /*stroke: #000;*/  stroke-width: 1.5px; cursor: pointer;}
.node.fixed { fill: #f00; cursor: pointer;}
text { font: 10px sans-serif; pointer-events: none; text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff; }
</style>
<body>
<script src="d3/d3.v3.js"></script>
<div id="topologyArea"></div>

<script>
var  nodes = [//it's not necessary to give x and y values to nodes. One gets created for every empty object you insert here like this {}
    {id: 1, x: 470, y: 410, icon: "images/abc.jpg"},
    {id: 2, x: 493, y: 364, icon: "images/abc.jpg"},
    {id: 3, x: 442, y: 365, icon: "images/abc.jpg"},
    {id: 4, x: 467, y: 314, icon: "images/abc.jpg"},
    {id: 5, x: 477, y: 248, icon: "images/fsd.jpg"},
    {id: 6, x: 425, y: 207, icon: "images/sdfs.jpg"},
    {id: 7, x: 402, y: 155, icon: "images/dfs.jpg"},
    {id: 8, x: 369, y: 196, icon: "images/abc.jpg"},
    {id: 9, x: 350, y: 148, icon: "images/abc.jpg"},
    {id: 10, x: 539, y: 222, icon: "images/abc.jpg"},
    {id: 11, x: 594, y: 235, icon: "images/abc.jpg"},
    {id: 12, x: 582, y: 185, icon: "images/abc.jpg"},
    {id: 13, x: 633, y: 200, icon: "images/abc.jpg"}
  ];
var links = [
    {id: 1, source:  0, target:  1},
    {id: 2, source:  1, target:  2},
    {id: 3, source:  0, target:  2},
    {id: 4, source:  1, target:  3},
    {id: 5, source:  3, target:  2},
    {id: 6, source:  3, target:  4},
    {id: 7, source:  4, target:  5},
    {id: 8, source:  5, target:  6},
    {id: 9, source:  5, target:  7},
    {id: 10, source:  6, target:  7},
    {id: 11, source:  6, target:  8},
    {id: 12, source:  7, target:  8},
    {id: 13, source:  9, target:  4},
    {id: 14, source:  9, target: 11},
    {id: 15, source:  9, target: 10},
    {id: 16, source: 10, target: 11},
    {id: 17, source: 11, target: 12},
    {id: 18, source: 12, target: 10}
  ];

var margin = {top: -5, right: -5, bottom: -5, left: -5},  width = 960 - margin.left - margin.right,  height = 500 - margin.top - margin.bottom;
var iconOffset = -10, iconSize = 20;
var mousedown_node = null, mouseup_node = null, mousedown_link = null;
var nodeDeletionActivated = false;

var zoom = d3.behavior.zoom().scaleExtent([0.2, 2]).on("zoom", zoomed);

var svg = d3.select("#topologyArea").append("svg").attr("width", width + margin.left + margin.right).attr("height", height + margin.top + margin.bottom).attr('class', 'background').attr("transform", "translate(" + margin.left + "," + margin.right + ")");
var rect = svg.append("rect").attr("fill","transparent").attr("width", width + margin.left + margin.right).attr("height", height + margin.top + margin.bottom)
            .on("mousedown", mousedownOnBackground);

rect.call(zoom);

var elementHolderLayer = svg.append("g");;
var linkLayer, nodeLayer;

d3.select(window).on("keydown", keydown);// add keyboard callback
redraw(elementHolderLayer);

function redraw(theLayer)//after updating the nodes and links arrays, use this function to re-draw the force graph
{   
    var force = d3.layout.force().size([width, height]).charge(-400).linkDistance(40).on("tick", tick);
    var dragElement = force.drag().on("dragstart", dragstarted);  
    linkLayer = null; nodeLayer = null;

    linkLayer = theLayer.selectAll(".link");
    nodeLayer = theLayer.selectAll(".node");

    linkLayer = linkLayer.data(links, function(d) {return d.id; }).exit().remove();
    linkLayer = theLayer.selectAll(".link").data(links, function(d) {return d.id; }).enter().append("line").attr("class", "link");

    nodeLayer = nodeLayer.data(nodes, function(d) {return d.id; }).exit().remove();
    nodeLayer = theLayer.selectAll(".node").data(nodes, function(d) {return d.id; }).enter().append("circle").attr("class", "node").attr("r", 12)

    .on("dblclick", dblclick).style("fill", function(d,i) { return d3.rgb(i*15, i*15, i*15); })
    .on("mouseup", function(d,i) { mouseup(d,i);})
    .on("mousemove", function(d,i) {mousemove(d,i);})
    .on("mousedown", function(d,i) {mousedown(d,i);})
    .call(dragElement)
    //.classed("dragging", true)
    .classed("fixed", function(d) {d.fixed = true;});

    force.nodes(nodes).links(links).start();

}//redraw


function tick() 
{
  linkLayer.attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });

  nodeLayer.attr("cx", function(d) {return d.x; }).attr("cy", function(d) { return d.y; });
}

function dblclick(d) { d3.select(this).classed("fixed", d.fixed = false); }
function dragstarted(d) 
{ 
    console.log("dragstarted for "+this);
    //d3.event.sourceEvent.stopPropagation();
    //d3.select(this).classed("dragging", true); 
    //d3.select(this).classed("fixed", d.fixed = true); 
}
function zoomed() { elementHolderLayer.attr("transform", "translate("+d3.event.translate+")scale(" + d3.event.scale + ")"); }


function spliceLinksForNode(node) //remove the links attached to a node that got deleted
{
  toSplice = links.filter(function(l) { return (l.source === node) || (l.target === node); });
  toSplice.map(function(l) {links.splice(links.indexOf(l), 1); });
}

function keydown() 
{
  //if (!selected_node && !selected_link) return;
  switch (d3.event.keyCode) 
  {
    case 8: 
    {// backspace
    }
    case 46:
    { // delete     
        if (mousedown_node)
        {
            selected_node = mousedown_node;
            if (selected_node) 
            {
                nodes.splice(nodes.indexOf(selected_node), 1);
                spliceLinksForNode(selected_node);
            }
            else if (selected_link) { links.splice(links.indexOf(selected_link), 1); }
            selected_link = null;
            selected_node = null;
            redraw(elementHolderLayer);
        }
      break;
    }
  }
}//keydown

function mousedown(d,i) {  mousedown_node = d;   console.log("mousedown"); }
function mousedownOnBackground() {resetMouseVars();}
function mousemove(d, i) {console.log("mousemove");}
function mouseup(d, i) {console.log("mouseup");}

function resetMouseVars() 
{
  mousedown_node = null;
  mouseup_node = null;
  mousedown_link = null;
}

</script>

.background{/*笔划:灰色;笔划宽度:1px;填充:rgb(252231216);*/光标:移动;}
.link{笔划:#000;笔划宽度:1.5px;}
.node{fill:#ccc;/*笔划:#000;*/笔划宽度:1.5px;光标:指针;}
.node.fixed{fill:#f00;cursor:pointer;}
文本{font:10px无衬线;指针事件:无;文本阴影:0 1px 0#fff,1px 0#fff,0-1px 0#fff,-1px 0#fff;}
var nodes=[//不必为节点指定x和y值。在此处插入的每个空对象都会创建一个值,如{}
{id:1,x:470,y:410,图标:“images/abc.jpg”},
{id:2,x:493,y:364,图标:“images/abc.jpg”},
{id:3,x:442,y:365,图标:“images/abc.jpg”},
{id:4,x:467,y:314,图标:“images/abc.jpg”},
{id:5,x:477,y:248,图标:“images/fsd.jpg”},
{id:6,x:425,y:207,图标:“images/sdfs.jpg”},
{id:7,x:402,y:155,图标:“images/dfs.jpg”},
{id:8,x:369,y:196,图标:“images/abc.jpg”},
{id:9,x:350,y:148,图标:“images/abc.jpg”},
{id:10,x:539,y:222,图标:“images/abc.jpg”},
{id:11,x:594,y:235,图标:“images/abc.jpg”},
{id:12,x:582,y:185,图标:“images/abc.jpg”},
{id:13,x:633,y:200,图标:“images/abc.jpg”}
];
变量链接=[
{id:1,源:0,目标:1},
{id:2,源:1,目标:2},
{id:3,源:0,目标:2},
{id:4,源:1,目标:3},
{id:5,源:3,目标:2},
{id:6,源:3,目标:4},
{id:7,来源:4,目标:5},
{id:8,来源:5,目标:6},
{id:9,来源:5,目标:7},
{id:10,来源:6,目标:7},
{id:11,来源:6,目标:8},
{id:12,来源:7,目标:8},
{id:13,来源:9,目标:4},
{id:14,来源:9,目标:11},
{id:15,来源:9,目标:10},
{id:16,来源:10,目标:11},
{id:17,来源:11,目标:12},
{id:18,来源:12,目标:10}
];
var margin={top:-5,right:-5,bottom:-5,left:-5},width=960-margin.left-margin.right,height=500-margin.top-margin.bottom;
变量iconOffset=-10,iconSize=20;
var mousedown\u node=null,mouseup\u node=null,mousedown\u link=null;
var nodeDeletionActivated=错误;
var zoom=d3.behavior.zoom();
var svg=d3.选择(“#地形区域”).附加(“svg”).attr(“宽度”,宽度+边距.左+边距.右).attr(“高度”,高度+边距.上+边距.下).attr('class','background').attr(“转换”,“转换”(+margin.left+),“+margin.right+”);
var rect=svg.append(“rect”).attr(“填充”、“透明”).attr(“宽度”,宽度+边距.左+边距.右)。attr(“高度”,高度+边距.上+边距.下)
.on(“mousedown”,mousedownOnBackground);
直接调用(缩放);
var elementHolderLayer=svg.append(“g”);;
变量链接层、节点层;
d3.选择(窗口)。打开(“向下键”,向下键);//添加键盘回调
重绘(elementHolderLayer);
函数redraw(theLayer)//更新节点和链接数组后,使用此函数重新绘制力图
{   
var-force=d3.layout.force().size([width,height])。charge(-400)。linkDistance(40)。on(“tick”,tick);
var dragElement=force.drag().on(“dragstart”,dragstarted);
linkLayer=null;nodeLayer=null;
linkLayer=theLayer.selectAll(“.link”);
nodeLayer=theLayer.selectAll(“.node”);
linkLayer=linkLayer.data(链接,函数(d){return d.id;}).exit().remove();
linkLayer=theLayer.selectAll(“.link”).data(links,函数(d){return d.id;})。enter().append(“line”).attr(“class”,“link”);
nodeLayer=nodeLayer.data(节点,函数(d){return d.id;}).exit().remove();
nodeLayer=theLayer.selectAll(“.node”).data(节点,函数(d){return d.id;})。enter().append(“circle”).attr(“class”,“node”).attr(“r”,12)
.on(“dblclick”,dblclick).style(“fill”,函数(d,i){返回d3.rgb(i*15,i*15,i*15);})
.on(“mouseup”,函数(d,i){mouseup(d,i);})
.on(“mousemove”,函数(d,i){mousemove(d,i);})
.on(“mousedown”,函数(d,i){mousedown(d,i);})
.呼叫(牵引)
//.classed(“拖动”,真)
.classed(“fixed”,函数(d){d.fixed=true;});
force.nodes(nodes).links(links.start();
}//重画
函数tick()
{
attr(“x1”,函数(d){返回d.source.x;})
.attr(“y1”,函数(d){返回d.source.y;})
.attr(“x2”,函数(d){返回d.target.x;})
.attr(“y2”,函数(d){返回d.target.y;});
attr(“cx”,函数(d){returnd.x;}).attr(“cy”,函数(d){returnd.y;});
}
函数dblclick(d){d3.select(this.classed)(“fixed”,d.fixed=false);}
函数dragstarted(d)
{ 
console.log(“dragstarted表示“+此”);
//d3.event.sourceEvent.stopPropagation();
//d3.选择(this).classed(“拖动”,true);
//d3.选择(this).classed(“fixed”,d.fixed=true);
}
函数zoomed(){elementHolderLayer.attr(“transform”、“translate”(+d3.event.translate+))scale(+d3.event.scale+);}
函数拼接链接ForNode(node)//删除附加到已删除节点的链接
{
toSplice=links.filter(函数(l){return(l.source==node)| |(l.target==node);});
map(函数(l){links.splice(links.indexOf(l),1);});
}
函数keydown()
{
//如果(!selected_node&&!selected_link)返回;
开关(d3.event.keyCode)
{
案例8:
linkLayer = linkLayer.data(links, function(d) {return d.id; })
           .exit()
           .remove(); 
linkLayer = theLayer.selectAll(".link").data(links, function(d) { return d.id; })
           .enter()
           .append("line")
           .attr("class", "link");
//Creating links
linkLayer = theLayer.selectAll(".link").data(links, function(d) {
     return d.id;
});
linkLayer.enter().append("line").attr("class", "link");
linkLayer.exit().remove();

//Creating Nodes with image icons
var gNodes = nodeLayer.enter().append("g")
   .attr("class", "node")
   .on("dblclick", dblclick).style("fill", function(d, i) {
        return d3.rgb(i * 15, i * 15, i * 15);
   })
   .on("mouseup", mouseup)
   .on("mousemove", mousemove)
   .on("mousedown", mousedown)
   .call(dragElement)         
   .classed("fixed", function(d) {
      d.fixed = true;
   });

gNodes.append("circle")
   .attr("r", 12);

gNodes.append("svg:image")
   .attr("class", "circle")
   .attr("xlink:href",function(d){ return d.icon })
   .attr("x", "-8px")
   .attr("y", "-8px")
   .attr("width", "16px")
   .attr("height", "16px");

nodeLayer.exit().remove(); 
function tick() {
  linkLayer.attr("x1", function(d) { return d.source.x; })
      .attr("y1", function(d) { return d.source.y; })
      .attr("x2", function(d) { return d.target.x; })
      .attr("y2", function(d) { return d.target.y; });

  nodeLayer.attr("transform", function(d) {return "translate("+d.x+","+d.y+")"; });
}