【发布时间】:2019-01-26 06:43:50
【问题描述】:
我有一个包含多个集群的 D3 可视化,我使用重力函数将所有圆圈都移到焦点的中心。然而,有了这个,圆圈是重叠的。
我尝试将这个块 https://bl.ocks.org/mbostock/3231298 转换为 V5,但我无法让它工作。
我使用负电荷来排斥节点,显然当我在tick中调用重力函数时,它会将代码带到集群焦点的中心
force = d3.forceSimulation(nodes)
.force('charge', d3.forceManyBody(-100))
.force('collision', d3.forceCollide().radius(function (d) {
return 1.1*d.radius;
}))
.on('tick', tick);
force.alpha(0.01);
force.alphaDecay = 0.1;
force.alphaTarget(.001);
force.force('x', d3.forceX().x(function (d) {
return foci[d.choice].x;
}))
force.force('y', d3.forceY().y(function (d) {
return foci[d.choice].y;
}))
console.log(JSON.stringify(foci));
// Draw circle for each node.
circle = svg.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("id", function (d) {
return d.id;
})
.attr("class", "node")
.style("stroke", "black");
;
// For smoother initial transition to settling spots.
// Need to research more on this
circle.transition()
.duration(100)
.delay(function (d, i) {
return i * 5;
})
.attrTween("r", function (d) {
var i = d3.interpolate(0, d.radius);
return function (t) {
return d.radius = i(t);
};
});
function tick(e) {
circle
.each(collide(0.5))
.each(gravity(.051 * .8))
.style("fill", function (d) {
//category is either 0 or 1
//so it's either 0+the choice or 6+the choice
//d.choice is between 0 and 5
multiplier = d.category
return colors[foci_count * multiplier + d.choice];
})
.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
})
.attr("r", function(d) {
return d.radius;
})
;
}
function collide(alpha) {
var quadtree = d3.quadtree().addAll(nodes);
return function (d) {
// var r = d.radius + maxNodeRadius + Math.max(padding, clusterPadding),
var r = d.radius + 10,
nx1 = d.x - r,
nx2 = d.x + r,
ny1 = d.y - r,
ny2 = d.y + r;
quadtree.visit(function (quad, x1, y1, x2, y2) {
console.log("visit")
if (quad.point && (quad.point !== d)) {
var x = d.x - quad.point.x,
y = d.y - quad.point.y,
l = Math.sqrt(x * x + y * y),
r = d.radius + quad.point.radius + 10;
console.log(d.cluster);
if (l < r) {
l = (l - r) / l * alpha;
d.x -= x *= l;
d.y -= y *= l;
quad.point.x += x;
quad.point.y += y;
}
}
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
});
};
}
// Move nodes toward cluster focus.
function gravity(alpha) {
return function (d) {
d.y += (foci[d.choice].y - d.y) * alpha;
d.x += (foci[d.choice].x - d.x) * alpha;
};
}
【问题讨论】:
-
为什么会有碰撞力,你叫碰撞在滴答声中? d3v5有重力。发挥力量的力量,如果重力大于碰撞,你就会重叠
-
我之所以在tick中调用collision是因为tick函数会更新节点的半径。而且我不希望圆圈在那段时间重叠。
-
然后用更新的节点重新初始化碰撞力
-
啊,是的,我正在尝试让它与使用四叉树的现有示例(使用 d3 v3)一起工作。感谢您为我指明正确的方向!
标签: d3.js