d3.js 图形链接的最小和最大长度

问题描述 投票:0回答:1

我想用d3做一个图形模拟,我可以拖动节点并移动它们,但链接的长度不能小于300或大于600,我该如何解决这个问题?

这是我的模拟:

const simulation = d3
  .forceSimulation(nodes)
  .force("charge", d3.forceManyBody().strength(-300))
  .force(
    "link",
    d3
      .forceLink(links)
      .id((d) => d.id)
      .distance(300),
  )
  .force(
    "center",
    d3.forceCenter(
      container.node().clientWidth / 2 - 75,
      container.node().clientHeight / 2 - 75,
    ),
  );

目前我只能设置链接的常量长度。

我尝试在 d3 文档中搜索,但没有找到任何内容,如果所描述的解决方案已经存在这样的问题,我会很高兴看到它。

谢谢!

javascript d3.js
1个回答
0
投票

我相信您必须实施自己的力量,因为没有任何内置力量支持您的用例。例如,forceLink.distance() 仅初始化一次力。

自定义实现看起来像这样(参见现场演示):

function linkForce(links, {
  min = 50, max = 200, strength = .5, id = d => d.id
} = {}) {
  const clamp = (a, b, v) => v <= a ? a : v >= b ? b : v;
  
  const update = (alpha) => {
    const s = .5 * alpha * strength;
    for(const {source: a, target: b} of links) {
      const dx = a.x + a.vx - b.x - b.vy;
      const dy = a.y + a.vy - b.y - b.vy;
      const dn = Math.hypot(dx, dy);
      const dc = clamp(min, max, dn);
      if(dn === dc) continue;
      const f = (dc - dn) / dn * .5 * alpha * strength;
      a.vx += dx * f;
      a.vy += dy * f;
      b.vx -= dx * f;
      b.vy -= dy * f;
    }
  };

  const initialize = nodes => {
    const map = new Map(nodes.map(d => [id(d), d]));
    for(const link of links) {
      link.source = map.get(link.source);
      link.target = map.get(link.target);
    }
  };
  
  return Object.assign(update, {initialize});
}
© www.soinside.com 2019 - 2024. All rights reserved.