更新: 我正在使用D3.js(javascript库)进行可视化。 我的要求如下:有多个组(表示为矩形框),每组中有多个节点数。我们获得了各个节点之间的链接集。 我也想使用强制定向布局。我们可以在屏幕上移动框和节点,链接也应相应移动。
我可以在框内创建框和节点,但无法创建链接。 链接未与节点对齐,并且链接也不根据节点的移动而移动。 谁能帮帮我吗?这是我的代码的jsfiddle链接。
http://jsfiddle.net/s6y183mh/32/
var width = 600,
height = 500;
radius =10;
var svg = d3.select("body").append("svg")
.attr("width", 900)
.attr("height", 800)
.style("background-color","#ECE9E9")
.attr("overflow","scroll");
// outer force layout
var graph = {
"nodes": [
{"name": "Probe1", "group": 1},
{"name": "Probe2", "group": 1},
{"name": "Probe3", "group": 1},
{"name": "Probe4", "group": 1},
{"name": "Probe5", "group": 2},
{"name": "Probe6", "group": 2}
],
"links": [
{"source": 1, "target": 0, "value": 1},
{"source": 2, "target": 0, "value": 8},
{"source": 3, "target": 0, "value": 10},
{"source": 3, "target": 2, "value": 6},
{"source": 4, "target": 0, "value": 1}
]
};
var outerData = [
{"group": "A"},
{"group": "B"},
{"group": "C"},
{"group": "D"},
{"group": "E"},
{"group": "F"},
{"group": "G"},
{"group": "H"},
{"group": "I"}
];
var outerLayout = d3.layout.force()
.size([800,800])
.charge(-8000)
.gravity(0.1)
.friction(.7)
.links([])
.nodes(outerData)
.on("tick", outerTick)
.start();
var outerNodes = svg.selectAll("g.outer")
.data(outerData, function (d) {return d.group;})
.enter()
.append("g")
.attr("class", "outer")
.attr("id", function (d) {return d.group;})
.call(outerLayout.drag());
outerNodes
.append("rect")
.style("fill", "#ECE9E9")
.style("stroke", "black")
.attr("height",120)
.attr("width",120);
var oNode = svg.selectAll(".outer")
.append("title")
.text(function(d) { return d.group; });
// inner force layouts
var innerAdata = {
"nodes": [
{"name": "Probe 1", "group": 1},
{"name": "Probe 2", "group": 1},
{"name": "Probe 3", "group": 1},
{"name": "Probe 4", "group": 1}
],
"links": [
{"source": 1, "target": 0, "value": 1},
{"source": 2, "target": 0, "value": 2}
]
};
var innerAlayout = d3.layout.force()
.size([100,100])
.charge(-400)
.gravity(0.75)
.links([])
.nodes(graph.nodes)
.on("tick", innerAtick)
.start();
var aNode = svg.select(".outer#A");
var innerAnodes = aNode.selectAll("g.inner")
.data(graph.nodes, function (d) {return d.name;})
.enter()
.append("g")
.attr("id", function (d) {return d.name;})
.call(innerAlayout.drag()
.on("dragstart", function(){
d3.event.sourceEvent.stopPropagation();
})
);
innerAnodes
.append("circle")
.style("fill", "#8DD623")
.style("stroke", "#8DD623")
.attr("r", 6)
.attr("class", "inner");
// functions
function outerTick (e) {outerNodes.attr("transform", function (d) {return "translate(" + d.x + "," + d.y + ")";});
outerNodes.attr("x", function(d) { return d.x = Math.max(20, Math.min(width, d.x)); })
.attr("y", function(d) { return d.y = Math.max(20, Math.min(height, d.y)); });
}
function innerAtick (e) {//innerAnodes.attr("cx", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
//.attr("cy", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });
innerAnodes.attr("transform", function (d) {return "translate(" + (d.x +10) + "," + (d.y +10) + ")";});
}
function changeForceOuter(charge, gravity) {
outerLayout.charge(charge).gravity(gravity);
}
function changeForceInner(charge, gravity) {
var tmp = "inner"+"A"+"Layout";
innerAlayout.charge(charge).gravity(gravity);
}
setTimeout(function(){ changeForceOuter(0,0);
changeForceInner(0,0);
}, 2000);
(function()
{
var force = d3.layout.force()
.gravity(.5)
.charge(-300)
.friction(.7)
.linkDistance(100)
.linkStrength(0)
.size([width, height]);
var link = svg.selectAll(".line")
.data(graph.links)
.enter().append("line")
.style("fill", "green" )
var temp = svg.selectAll(".inner")
.style("fill","red");
var node = svg.selectAll(".inner")
//.data(graph.nodes)
.append("title")
.text(function(d) { return d.name; });
node = svg.selectAll(".inner")
.data(graph.nodes)
.enter().append("circle")
.attr("r", radius - .75)
.style("fill", "red" );
node.append("title")
.text(function(d) { return d.name; });
force
.nodes(graph.nodes)
.links(graph.links)
.on("tick", tick)
.start();
/*while (force.alpha() >0.005) {
force.tick();
}*/
function changeForce(charge, gravity) {
force.charge(charge).gravity(gravity);
}
//----------------------------
function tick() {
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.attr("cx", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
.attr("cy", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });
link.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; });
}
function changeForce(charge, gravity) {
force.charge(charge).gravity(gravity);
}
changeForce(0, 0);
})();