为何d3.forceSimulation模拟结果不总是对称?
无摩擦油面漂浮磁铁模拟的对称疑问
我正在做一个无摩擦油面上漂浮磁铁的模拟:磁铁的作用力与其半径相关,会自由移动直至达到受力平衡状态。我原本认为这种平衡状态下,磁铁应该始终呈现对称排列,但用D3实现后,结果并不总是对称的——即使拖拽元素,它们也不会总是回到同一位置。
想确认:是我的对称理论本身错误?元素本就不该固定回到同一位置?还是力的构建逻辑存在问题?

实现代码
JavaScript
// Source: https://bl.ocks.org/HarryStevens/f636199a46fc4b210fbca3b1dc4ef372 var radius = 160; var positives = [27, 50, 20, 20]; var negatives = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10]; /* Änderungen der Konfiguration nur oberhalb dieser Zeile */ var width = 400, height = 400; var myNodes = []; for (let i = 0; i < positives.length; i++) { myNodes.push({ charge: -positives[i] }); } for (let i = 0; i < negatives.length; i++) { myNodes.push({ charge: negatives[i] }); } var nodePadding = 10; var svg = d3.select("svg").attr("width", width).attr("height", height); var simulation = d3 .forceSimulation() .nodes(myNodes) .force( "forceX", d3 .forceX() .strength(0.1) .x(width * 0.5) ) .force( "forceY", d3 .forceY() .strength(0.1) .y(height * 0.5) ) .force( "center", d3 .forceCenter() .x(width * 0.5) .y(height * 0.5) ) .force( "charge", d3.forceManyBody().strength(function (d) { return -d.charge * 10; }) ) .force( "radial", d3.forceRadial( function (d) { return d.charge > 0 ? radius : 0; }, width / 2, height / 2 ) ) .force( "collide", d3.forceCollide().radius(function (d) { return Math.abs(d.charge) + nodePadding; }) ) .on("tick", function (d) { node .attr("cx", function (d) { return d.x; }) .attr("cy", function (d) { return d.y; }); }); svg .append("circle") .classed("radius", true) .attr("cx", width / 2) .attr("cy", height / 2) .attr("r", radius) .style("fill", "none") .style("stroke", "#bbb") .style("stroke-dasharray", 4); var node = svg .selectAll(".node") .data(myNodes) .join("circle") .classed("node", true) .attr("r", function (d) { return Math.abs(d.charge); }) .attr("fill", function (d) { return d.charge > 0 ? "#0000ff" : "#ff0000"; }) .attr("cx", function (d) { return d.x; }) .attr("cy", function (d) { return d.y; }); d3.selectAll("circle").call( d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended) ); distance = ([x1, y1], [x2, y2]) => Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); function dragstarted(event, d) { if (!event.active) simulation.alphaTarget(0.03).restart(); d.fx = d.x; d.fy = d.y; } function dragged(event, d) { d.fx = event.x; d.fy = event.y; } function dragended(event, d) { if (event.active) simulation.alphaTarget(0.03); d.fx = null; d.fy = null; }
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script> <div id="content"> <svg width="400" height="400"> </svg> </div>
内容的提问来源于stack exchange,提问作者Vale
相关产品推荐
相关产品推荐

