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+")"; });
}