【问题标题】:force graph in d3.js - disappearing nodesd3.js 中的强制图 - 消失的节点
【发布时间】:2013-10-17 22:48:39
【问题描述】:

我正在尝试在 d3.js 中构建一个有向力图,它上面有一个点击监听器,它可以更改基础数据并重绘图形。我相信我正在遵循 Bostock 先生的更新模式,但我遇到的问题是,当我运行由点击侦听器触发的更新时,节点会从屏幕底部消失,留下链接和标签。

此更新似乎运行,更新现有节点(在这种情况下将它们变为绿色)然后忽略“进入”和“退出”部分(这是所需的行为)然后点击发送节点的 tick() 函数南。

我可以通过删除节点上的“g”标签来实现这个工作,从而将标签和节点解耦,这显然是不可取的。

我不禁觉得我错过了一些明显的东西!或者也许我应该以不同的方式解决这个问题?

代码如下:

var width = 960,
    height = 500,
    links,
    nodes,
    root;

var force = d3.layout.force()
    .size([width, height])
    .charge(-200)
    .linkDistance(50)
    .on("tick", tick);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var link = svg.selectAll(".link"),
    node = svg.selectAll(".node");

d3.json("test.json", function(json) {
  root = json;
  update();
});

function update() {
  nodes = root.nodes
  links = root.links

  // Restart the force layout.
  force
      .nodes(nodes)
      .links(links)
      .start();

    svg.append("svg:defs").append("marker")
        .attr("id", "end")
        .attr("refX", 15)
        .attr("refY", 2)
        .attr("markerWidth", 6)
        .attr("markerHeight", 4)
        .attr("orient", "auto")
        .append("svg:path")
        .attr("d", "M 0,0 V 4 L8,2 Z");

  // Update the links…
  //link = link.data(links, function(d) { return d.target.name; });
  link = link.data(links)

  // Exit any old links.
  link.exit().remove();

  // Enter any new links.
  link.enter().insert("svg:line", ".node")
      .attr("class", "link")
      .attr("marker-end", "url(#end)")
      .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; });

  // Update the nodes…
  node = svg.selectAll("g").select(".node").data(nodes, function(d) { return d.name; });


  node.style("fill", "green")

  // Exit any old nodes.
  node.exit().remove();

  // Enter any new nodes.
  node.enter().append("g")
      .append("svg:circle")
      .attr("class", "node")
      .attr("id", function(d) {return "node" + d.index; })
      .attr("r", 12)
      .style("fill", "#BBB")
      .on("click", click)
      .call(force.drag);

  node.append("svg:text")
      .attr("dx", 16)
      .attr("dy", ".15em")
      .attr("class", "nodelabel")
      .text(function(d) { return d.name });
}

function tick() {
  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 "translate(" + d.x + "," + d.y + ")"; });

}


function click(d) {
  if (!d3.event.defaultPrevented) {

    // DO ANYTHING
    update()
  }
}

test.json 的内容是:

{
  "nodes": [
    {"name" : "John"},
    {"name" : "Alison"},
    {"name" : "Phil"},
    {"name" : "Jim"},
    {"name" : "Jane"},
    {"name" : "Mary"},
    {"name" : "Joe"}
  ],
  "links": [
    {"source":  1, "target":  0},
    {"source":  2, "target":  0},
    {"source":  3, "target":  0},
    {"source":  4, "target":  0},
    {"source":  5, "target":  1},
    {"source":  6, "target":  1}
  ]
}

【问题讨论】:

  • 强制布局不允许您重置节点和链接。要更改它们,只需设置一次,然后修改底层数据结构。不要多次拨打force.nodes()force.links()
  • 很高兴知道,谢谢。但是,如果我将该块移到 update() 函数之外,我仍然会遇到同样的问题。
  • 您还必须在update() 中再次进行选择——您的变量link 包含执行选择的结果。
  • 另一个好地方。将该行更改为 link = svg.selectAll(".link").data(links) 没有任何效果。我实际上并没有更改基础数据。
  • 等等,如果你不改变数据,你想更新什么?

标签: d3.js force-layout


【解决方案1】:

好的,所以我找到了问题所在。当我选择要更新的节点时,我正在选择节点(即具有“节点”类的元素)并且它们正在被更新:

node = svg.selectAll("g").select(".node").data(nodes, function(d) { return d.name; });

然后在 tick 函数中我正在更新这些节点:

node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

所以这很正确,但是,节点与文本标签一起被封装在“g”标签中,但tick() 函数仅作用于节点。解决方法是强制 tick() 中的 transform 属性更新整个组,而不仅仅是节点:

svg.selectAll("g").attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

现在一切正常!

【讨论】:

    猜你喜欢
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 2016-08-15
    • 1970-01-01
    相关资源
    最近更新 更多