如何解决D3强制拉力/避免节点重叠力碰撞,半径
我试图通过使用d3强制布局来创建群集气泡。 在参考了几个代码之后,我可以创建以下图表。 但是,问题在于圆圈彼此重叠。 我提到了这个问题的几个问答,但仍然无法解决问题。
我试图制作类似以下网站的图表。(https://blockbuilder.org/ericsoco/d2d49d95d2f75552ac64f0125440b35e) 我已经添加了forcecollide,但是它似乎不起作用。
有人可以帮助解决这个问题吗?
此图表的代码如下。
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="my_dataviz"></div>
<script src="https://d3js.org/d3.v5.js"></script>
<script>
// set the dimensions and margins of the graph
var width = 450
var height = 450
// append the svg object to the body of the page
var svg = d3.select("#my_dataviz")
.append("svg")
.attr("width",450)
.attr("height",450),color = d3.scaleOrdinal(d3.schemeAccent);
// create dummy data -> just one element per circle
var data = [{ "name": "A",value:10},{ "name": "B",value:20 },{ "name": "C",{ "name": "D",value:60 },{ "name": "E",{ "name": "F",value:20 },{ "name": "G",value:50 },{ "name": "H",value:100 }]
// Initialize the circle: all located at the center of the svg area
var node = svg.append("g")
.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("r",d => d.value)
.attr("cx",width / 2)
.attr("cy",height / 2)
.style("fill",d=>color(d.name))
.style("fill-opacity",0.9)
// .attr("stroke","#b3a2c8")
.style("stroke-width",4)
.call(d3.drag() // call specific function when circle is dragged
.on("start",dragstarted)
.on("drag",dragged)
.on("end",dragended));
var transitionTime = 3000;
var t = d3.timer(function (elapsed) {
var dt = elapsed / transitionTime;
simulation.force('collide').strength(Math.pow(dt,2) * 0.7);
if (dt >= 1.0) t.stop();
});
// Features of the forces applied to the nodes:
var simulation = d3.forceSimulation()
.force("center",d3.forceCenter().x(width / 2).y(height / 2)) // Attraction to the center of the svg area
.force("collide",d3.forceCollide().strength(1).radius(30).iterations(1)) // Force that avoids circle overlapping
.force('attract',d3.forceRadial(0,width / 2,height / 2).strength(0.07))
// Apply these forces to the nodes and update their positions.
// Once the force algorithm is happy with positions ('alpha' value is low enough),simulations will stop.
simulation
.nodes(data)
.on("tick",function(d){
node
.attr("cx",function(d){ return d.x; })
.attr("cy",function(d){ return d.y; })
});
// What happens when a circle is dragged?
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(.03).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) simulation.alphaTarget(.03);
d.fx = null;
d.fy = null;
}
</script>
</body>
</html>
解决方法
在collide
中,30
的常量为radius
,如果传递回调函数以返回节点值(您的节点半径),则问题应解决了。这是我的操作方式:
.force("collide",d3.forceCollide().strength(1).radius( (d) => d.value ).iterations(1))
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。