如何在不使用定心力的情况下定心节点?

时间:2019-05-30 11:15:59

标签: d3.js centering force-layout

我有一个强制布局图,用户可以在其中动态添加节点。我如何才能使所有节点之间居中放置一点距离,并使它们独立移动而不是绕中心移动。

我尝试删除d3.forceCenter(width / 2, height / 2),它使节点独立移动,但随后所有节点都位于(0,0)。

simulation = d3.forceSimulation()
    .force('charge', d3.forceManyBody().strength(0))
    .force('center', d3.forceCenter(width / 2, height / 2));

我希望所有节点都居中并独立移动。

编辑:

我尝试设置cxcy的值,但这也不起作用。

  const nodeEnter = nodeElements
    .enter()
    .append('circle')
    .attr('r', 20)
    .attr('fill', 'orange')
    .attr('cx', (d, i) => {
      return (width / 2) + i * 10;
    })
    .attr('cy', (d, i) => {
      return (height / 2) + i * 10;
    })
    .call(dragDrop(simulation))
    .on('click', ({ id }) => handleClick(id));

1 个答案:

答案 0 :(得分:0)

给出您在your comment中所说的话...

  

如果我移动1个节点,则所有其他节点相对移动,以使质心保持在同一位置。

...您已经知道forceCenter是执行该任务的错误工具,因为它将保持重心。

因此,只需将其替换为forceXforceY

const simulation = d3.forceSimulation()
    .force('centerX', d3.forceX(width / 2))
    .force('centerY', d3.forceY(height / 2));

由于您没有提供足够的代码,因此这里是一个常规演示:

svg {
  background-color: wheat;
}
<svg width="400" height="300"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
  const svg = d3.select('svg');

  const width = svg.attr('width');
  const height = svg.attr('height');

  const data = d3.range(50).map(() => ({}));

  const node = svg.selectAll()
    .data(data)
    .enter()
    .append('circle')
    .attr('r', 10)
    .attr('fill', 'teal')
    .attr('stroke', 'black')
    .call(d3.drag()
      .on('start', dragstarted)
      .on('drag', dragged)
      .on('end', dragended));

  const simulation = d3.forceSimulation()
    .force('charge', d3.forceManyBody().strength(-15))
    .force('centerX', d3.forceX(width / 2))
    .force('centerY', d3.forceY(height / 2));

  simulation
    .nodes(data)
    .on('tick', ticked);

  function ticked() {
    node.attr('cx', d => d.x)
      .attr('cy', d => d.y);
  }

  function dragstarted(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).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(0);
    d.fx = null;
    d.fy = null;
  }
</script>