Как центрировать узлы, не используя центрирующую силу? - PullRequest
0 голосов
/ 30 мая 2019

У меня есть график раскладки, где пользователь динамически добавляет узлы. Как я могу центрировать все мои узлы с небольшим расстоянием между ними, и заставить их перемещаться независимо, а не вокруг центра.

Я попытался удалить 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));

Я хочу, чтобы все узлы были отцентрированы и перемещались независимо.

РЕДАКТИРОВАТЬ:

Я пытался установить значения cx и cy, но это тоже не сработало.

  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 голосов
/ 30 мая 2019

Учитывая то, что вы сказали в ваш комментарий ...

Если я перемещаю 1 узел, то все остальные узлы перемещаются относительно, чтобы центр масс оставался в том же месте.

... вы уже знаете, что forceCenter - неподходящий инструмент для этой задачи, поскольку он будет сохранять центр масс.

Поэтому просто замените его на forceX и forceY:

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>
...