0
我正尝试使用d3.js v4创建一个强制布局,并且市长部分在使用拖动行为时非常适合接受一个问题。D3.js v4使用链接力强制布局会在使用拖动行为时导致奇怪的移动
当拖动它周围的其他节点,它们没有连接到点击节点的节点上单击,飞走:
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
function drawNode(nodes) {
return svg.selectAll("circle.node")
.data(nodes, function (d, i) { return d.Id; })
.enter().append("circle")
.attr("class", "node")
.attr("r", 5)
.attr("fill", "blue")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
}
function drawMainNode(nodes) {
return svg.selectAll("circle.mainnode")
.data(nodes, function (d, i) { return d.Id; })
.enter().append("circle")
.attr("class", "mainnode")
.attr("r", 15)
.attr("fill", "red")
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
}
function drawLinks(links) {
return svg.selectAll("line")
.data(links, function (d, i) { return d.source + "-" + d.target; })
.enter().append("line")
.attr("stroke-width", 3);
}
function dragstarted(d) {
if (!d3.event.active) dragSimualtion.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) dragSimualtion.alphaTarget(0);
d.fx = null;
d.fy = null;
}
function ticked() {
dLinks
.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; });
dNodes
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
dMainNodes
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
var dLinks = drawLinks(mainLinks.concat(nodeLinks));
var dNodes = drawNode(nodes);
var dMainNodes = drawMainNode(mainNodes);
var simulation = d3.forceSimulation(mainNodes.concat(nodes))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width/2, height/2))
.force("collide", d3.forceCollide(20).radius(20))
.force("links", d3.forceLink(mainLinks.concat(nodeLinks))
.id(function (d) { return d.Id; }))
.alpha(0.9)
.alphaDecay(0.1)
.on("tick", ticked);
var dragSimualtion = d3.forceSimulation(mainNodes.concat(nodes))
.force("collide", d3.forceCollide(20).radius(20))
.force("links", d3.forceLink(mainLinks.concat(nodeLinks))
.id(function (d) { return d.Id; }))
.alphaDecay(0.1)
.on("tick", ticked)
.stop()
我试图用一个单独的模拟拖事件只使用链接力和碰撞力 - 因为节点应该与附属于它们的每个节点一起拖动,而其他非附加节点应该被推开,但只有在它们相互碰撞时才会被推开。
所以问题是,我如何防止其他节点飞来飞去?
EDIT1:我第一次尝试使用只有第一个模拟对象,但我认为观察到的效果是由d3.forceManyBody
由于其斥力而引起的。我试图用distanceMax
来限制这种影响,但没有成功。我的第二次尝试是使用单独的d3.forceSimulation
,它只包含与拖动动画相关的力。
这可能是因为'd3.forceManyBody'和'd3.forceCollide'的组合。我真的不认为你需要单独的模拟拖动事件。只需更新默认的一个。见https://bl.ocks.org/mbostock/2675ff61ea5e063ede2b5d63c08020c7 – mahish
我的第一次尝试是只使用一个模拟,但我认为节点的漂移效应是由ManyBody力(由于斥力)引起的,所以我创建了第二次模拟。我也尝试用d3.forceManyBody的disferentialMax()来将排斥力限制在一定范围内。 –