使用 D3.js force 时如何防止气泡接触 svg 框架/边框?

问题描述

我正在使用 D3.js 库来开发气泡图。我从互联网上得到了一些使用力模拟来显示气泡节点的示例。我非常喜欢它并考虑将它包含在我的项目中,但存在一个问题,有时气泡会被周围的 SVG 框架/边框切割。我试着理解和调试代码,我得出结论,气泡的最终位置是由力模拟决定的。 我想到了以下两种解决方案:

  1. 限制指定区域内的气泡(实际SVG帧尺寸可以更大)
  2. 根据 D3 力模拟导致气泡占据的区域,预定义框架的大小(宽度/高度)。换句话说,确定将通过力模拟计算的区域,然后定义 SVG 宽度/高度

有什么方法可以实现我提到的两种解决方案之一?有没有其他解决方案可以防止受力模拟气泡不接触SVG框架/边框?

解决方法

第二种方法不可行,因为力模拟过于非线性且不可预测,无法预先确定其作用范围。此外,根据作用力的不同,节点可以无限期地排斥自己,因此在模拟过程中扩展 SVG 可以创建一个不断扩展的 SVG 元素。

第一种方法是要走的路。要限制气泡,您可以编辑更新位置的函数(在示例中通常称为 ticked())并使用 Math.min()手动添加边界> 和 Math.max()

以下代码来自this example

function tick() {
    node
      .attr("cx",function(d) { return d.x = Math.max(radius,Math.min(width - radius,d.x)); })
      .attr("cy",function(d) { return d.y = Math.max(radius,Math.min(height - radius,d.y)); });
  }

注意事项:

  1. 记得计算气泡的半径,使其与边界相切。

  2. 注意,代码不仅返回有限值,还将其赋值给d.x和d.y。这是必要的,因为模拟使用 d.x 和 d.y 的当前值来计算模拟的下一帧。