力模拟为新节点生成 NaN 坐标



我是D3.js框架的新手,正在寻求帮助。我正在尝试使用简单的力模拟绘制网络。我希望每秒添加一个新节点并加入模拟。

以下是我的尝试。我用两个节点启动模拟游戏,它们表现得很好。但是,当我添加第三个节点时,模拟会为其 x 和 y 坐标分配 NaN 值。

.HTML:

<head>
<script src="https://d3js.org/d3.v4.js"></script>
</head>
<body>
  <svg width="300" height="300"></svg>
</body>

Javascript:

const svg = d3.select('svg');
const height = +svg.attr('height');
const width = +svg.attr('width');
// Test Data
const nodes = [ {}, {} ];
setTimeout(() => {
  nodes.push({});
  redraw();
}, 2000);
const ticked = () => {
  svg.selectAll('g.node')
    .attr('transform', d => {
      if (isNaN(d.x) || isNaN(d.y)) {
        console.error('nan!!!');
        d.x = 50;
        d.y = 50;
      }
      return `translate(${d.x},${d.y})`;
    });
};
const simulation = d3.forceSimulation()
  .force('repulsion', d3.forceManyBody().strength(-30))
  .force('pin_y_to_center', d3.forceY().y(d => height / 2).strength(0.1))
  .force('pin_x_to_center', d3.forceX().x(d => width / 2).strength(0.1));
simulation.nodes(nodes);
simulation.on('tick', ticked);
const redraw = () => {
  const node = svg
    .selectAll('.node')
    .data(nodes)
    .enter().append('g');
  node.attr('class', 'node')
    .append('circle')
      .attr('r', 5);
};
redraw();

您必须将数组传递给模拟...

simulation.nodes(nodes);

。在redraw函数内。

以下是仅包含该更改的代码:

const svg = d3.select('svg');
const height = +svg.attr('height');
const width = +svg.attr('width');
// Test Data
const nodes = [{}, {}];
setTimeout(() => {
  nodes.push({});
  redraw();
}, 2000);
const ticked = () => {
  svg.selectAll('g.node')
    .attr('transform', d => {
      if (isNaN(d.x) || isNaN(d.y)) {
        console.error('nan!!!');
        d.x = 50;
        d.y = 50;
      }
      return `translate(${d.x},${d.y})`;
    });
};
const simulation = d3.forceSimulation()
  .force('repulsion', d3.forceManyBody().strength(-30))
  .force('pin_y_to_center', d3.forceY().y(d => height / 2).strength(0.1))
  .force('pin_x_to_center', d3.forceX().x(d => width / 2).strength(0.1));
simulation.on('tick', ticked);
const redraw = () => {
  simulation.nodes(nodes);
  const node = svg
    .selectAll('.node')
    .data(nodes)
    .enter().append('g');
  node.attr('class', 'node')
    .append('circle')
    .attr('r', 5);
};
redraw();
<script src="https://d3js.org/d3.v4.js"></script>
<svg width="300" height="300"></svg>

此外,请考虑在附加新节点后重新加热模拟。

最新更新