javascript - 从强制布局中删除两个节点失败,而一个节点成功

标签 javascript d3.js

我正在尝试从强制布局中删除一些节点。

该过程的第一部分是选择一个或多个节点。这是通过点击处理程序完成的:

  var nodeg = node.enter().append("g")
    .attr("class", "node")
    .on('click', function (n) {
      if (n.dragging === true) {
        return;
      }

      // select the clicked node
      n.selected = !n.selected;

      d3.select(this)
        .transition()
        .duration(500)
        .ease('bounce')
        .attr('fill', getNodeBackground(n))
        .attr('transform', getNodeTransform(n));
    })
    .call(drag);

请注意,我将 selected 设置为 true。

接下来,如果用户按下delete键,我将删除选定的节点:

function removeSelectedNodes() {
  if (!confirm('Are you sure you want to delete the selected relationships?')) {
    return;
  }

  var firstIndex = -1;
  d3.selectAll('.node')
    .each(function (n, i) {
      if (n.selected !== true) {
        return;
      }

      n.data.remove = true;
      n.data.index = i;

      if (firstIndex === -1) {
        firstIndex = i;
      }
    });

  var offset = 0;
  _.each(_.where(scope.nodes, {data: {remove: true}}), function (n) {
    var removeAt = n.index;
    if (n.index > firstIndex) {
      removeAt = n.index - 1 - offset;
      offset++;
    }

    scope.nodes.splice(removeAt, 1);
    scope.links.splice(removeAt - 1, 1);
  });

  renderGraph();
}

整个renderGraph函数如下所示:

function renderGraph() {
  force
    .nodes(scope.nodes)
    .links(scope.links)
    .start();

  var link = svg.selectAll(".link")
    .data(scope.links);
  link.exit().remove();

  link.enter().append("line")
    .attr("class", "link");

  var node = svg.selectAll(".node")
    .data(scope.nodes);
  node.exit().remove();

  var nodeg = node.enter().append("g")
    .attr("class", "node")
    .on('click', function (n) {
      if (n.dragging === true) {
        return;
      }

      // select the clicked node
      n.selected = !n.selected;

      d3.select(this)
        .transition()
        .duration(500)
        .ease('bounce')
        .attr('fill', getNodeBackground(n))
        .attr('transform', getNodeTransform(n));
    })
    .call(drag);

  nodeg.append("image")
    .attr("xlink:href", function (d) {
      return d.avatar || 'https://github.com/favicon.ico'
    })
    .attr("x", -56)
    .attr("y", -8)
    .attr("width", 64)
    .attr("height", 64);

  nodeg.append("text")
    .attr("dx", 12)
    .attr("dy", ".35em")
    .attr('class', 'name')
    .text(function (d) {
      return d.displayName;
    });

  nodeg.append("text")
    .attr("dx", 12)
    .attr("dy", "1.35em")
    .text(function (d) {
      return d.relationship;
    });

  force.on("tick", function () {
    link.attr("x1", function (d) {
      return d.source.x;
    })
      .attr("y1", function (d) {
        return d.source.y;
      })
      .attr("x2", function (d) {
        return d.target.x;
      })
      .attr("y2", function (d) {
        return d.target.y;
      });

    node.attr("transform", function (d) {
      return getNodeTransform(d);
    });
  });
}

这就是它开始向南移动的地方。如果我选择一个节点,则拼接节点后图形将正确渲染。但是,如果我删除两个节点,图表最终会保留第一个删除的节点(按索引)。

假设第一个节点(按索引)是“Bob”,第二个节点是“Bill”。第二个节点将被删除,但第一个节点将保留。有趣的是,另一个节点,即当前的最后一个节点(按索引)将消失。

注意:数组看起来不错。我想要删除的节点已经消失了,剩下的都是正确的。

我在这里做错了什么?

更新:我尝试在删除节点后不设置节点链接,并且只需调用start:

force.start()

这不起作用。

最佳答案

再次感谢 Lars,答案是向链接和节点添加关键功能:

  var link = svg.selectAll(".link")
    .data(scope.links, function (d) {
      return d.source.data._id + '|' + d.target.data._id;
    });

  var node = svg.selectAll(".node")
    .data(scope.nodes, function (d) {
      return d.data._id;
    });

谢谢拉尔斯!

关于javascript - 从强制布局中删除两个节点失败,而一个节点成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33255265/

相关文章:

d3.js - d3 图形大小未更新

javascript - 通过更新变量更新 D3 图表的大小

javascript - OnKeyDown或KeyPress,检测插入字符的位置

javascript - 在数组数组中循环

javascript - 将元素始终定位在死点的流体图像上方?

javascript - Firefox 中的 D3.js 转换错误?

javascript - D3 饼图中的标签被 chop

javascript - 在 Firefox 扩展中使用 jQuery 扩展

javascript - 为什么我不能在这里访问 jquery select val ?

javascript - 如何使用 d3.js 库使桑基图中的节点可点击