我正在尝试在主要功能之外运行d3.forceSimulation()。 我这样做是为了能够在其他函数中调用模拟。
其他功能
function draw_network(nodes, links){
var graph = {};
graph.links = links;
graph.nodes = nodes;
graph = JSON.stringify(graph);
graph = JSON.parse(graph);
console.log(graph);
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var simulation = d3.forceSimulation()
.nodes(graph.nodes)
.force("link", d3.forceLink().id(function(d) { return d.id; }).distance(100))
.force('charge', d3.forceManyBody()
.strength(-2500)
.theta(0.8)
)
.force("center", d3.forceCenter(width / 2, height / 2));
var g = svg.append("g")
.attr("class", "everything");
//add zoom capabilities
var zoom_handler = d3.zoom()
.on("zoom", zoom_actions);
zoom_handler(svg);
//Zoom functions
function zoom_actions(){
g.attr("transform", d3.event.transform)
}
// Load network
run(graph, simulation);
};
function run(graph, simulation) {
graph.links.forEach(function(d){
d.source = d.Source;
d.target = d.Target;
});
var g = d3.select(".everything");
// Set links
var link = g.append("g")
.attr("class", "links")
.selectAll("line")
.data(graph.links)
.enter().append("line")
.attr("class", "link")
.on('mouseout', fade(1))
.attr("stroke-width", 2);
// Set nodes
var node = g.append("g")
.attr("class", "nodes")
.selectAll("g")
.data(graph.nodes)
.enter()
.append("circle")
.attr("class", "circle");
// Set rectangle begind label
var rect = g.append("g")
.attr("class", "rects")
.selectAll("rect")
.data(graph.nodes)
.enter().append("rect")
.attr("class", "rect")
.attr("rx", 5) // round shape
.attr("ry", 5);
// Set labels
var label = g.append("g")
.attr("class", "labels")
.selectAll("text")
.data(graph.nodes)
.enter().append("text")
.attr("class", "label")
.attr("dx", 0)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.id; });
/* Configuration of simulation */
simulation
.nodes(graph.nodes)
.on("tick", ticked(graph, node, link, rect, label));
simulation.force("link")
.links(graph.links);
} // End function run
//////////////////////////////////////
/* Set position of network element */
/////////////////////////////////////
function ticked(data, node, link, rect, label) {
d3.select("svg").selectAll("text").each(function(d, i) {
data.nodes[i].bb = this.getBBox(); // get bounding box of text field and store it in texts array
});
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; })
.style("stroke", "#aaa");
node
.attr("cx", function (d) { return d.x; })
.attr("cy", function (d) { return d.y; })
.attr("r", 30)
.attr("fill", function(d){
if(d.search == true) {
return "black";
}else{
return "grey";
}
})
.on('mouseover', fade(0.1, node, link, data))
.on('mouseout', fade(1, node, link, data))
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
rect
.attr("x", function(d) { return d.x - d.bb.width/2-2; })
.attr("y", function(d) { return d.y - d.bb.height/2; })
.attr("width", function(d) { return d.bb.width + 4; })
.attr("height", function(d) { return d.bb.height; })
.style("fill", "white")
.style("opacity", 0.7);
label
.attr("x", function(d) { return d.x; })
.attr("y", function (d) { return d.y; })
.style("font-size", "14px")
.style("fill", "#000");
} // end function ticked
function fade(opacity, node, link, graph) {
return d => {
node.style('stroke-opacity', function (o) {
const thisOpacity = isConnected(d, o, graph) ? 1 : opacity;
this.setAttribute('fill-opacity', thisOpacity);
return thisOpacity;
});
link.style('stroke-opacity', o => (o.source === d || o.target === d ? 1 : opacity));
};
};
function isConnected(a, b, graph) {
/* On node mouseover, highlight connected node */
const linkedByIndex = {};
graph.links.forEach(d => {
linkedByIndex[`${d.source.index},${d.target.index}`] = 1;
});
return linkedByIndex[`${a.index},${b.index}`] || linkedByIndex[`${b.index},${a.index}`] || a.index === b.index;
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart()
d.fx = d.x
d.fy = d.y
// simulation.fix(d);
}
function dragged(d) {
d.fx = d3.event.x
d.fy = d3.event.y
}
function dragended(d) {
d.fx = d3.event.x
d.fy = d3.event.y
if (!d3.event.active) simulation.alphaTarget(0);
setTimeout(function(){
simulation.stop();
}, 2000);
}
在我的主要代码中,我致电:
draw_network(nodes, links);
当前我得到了节点,但是尚未对其进行仿真,并且当节点之间的链接应该将节点连接在一起时,它们位于左上角。