d3 v4更新/合并分组数据

时间:2016-08-08 16:52:22

标签: javascript d3.js

我正在尝试更新D3 v4中的力模拟数据,类似于this unsuccessful attempt,半近似this successful one。 CodePen here

而不是加入新节点,它似乎是所有节点加倍(见图片)。它似乎也没有正确刷新图表。

initial graph (初始图表)

graph after adding data (添加数据后)

HTML:

<button onclick="addData()">Add Data</button>
<svg width="960" height="600"></svg>

JavaScript的:

function addData() {
    graph.nodes.push({"id": "Extra1", "group": 11},{"id": "Extra2", "group": 11})
    graph.links.push({"source": "Extra1", "target": "Valjean", "strength": 1},{"source": "Extra1", "target": "Extra2", "strength": 2})
    update()
    simulation.restart()
}

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

var link, linkEnter, nodeWrapper, nodeWrapperEnter;

var simulation = d3.forceSimulation()
    .force("link", d3.forceLink().id(function(d) { return d.id; }))
    .force("charge", d3.forceManyBody())
    .force("center", d3.forceCenter(width / 2, height / 2))
    .on("tick", ticked);

var allLinkG = svg.append("g")
    .attr("class", "allLinkG")

var allNodeG = svg.append("g")
    .attr("class", "allNodeG")

update()
simulation.restart()

function update(){

  link = allLinkG
    .selectAll("line")
    .data(graph.links, function(d){ return d.id }) 

  link.exit().remove()

  linkEnter = link
    .enter().append("line");

  link = linkEnter.merge(link).attr("class","merged");


  nodeWrapper = allNodeG
    .selectAll("nodeWrapper")
    .data(graph.nodes, function(d) { return d.id; })

  nodeWrapper.exit().remove();

  nodeWrapperEnter = nodeWrapper.enter()
    .append("g").attr("class","nodeWrapper")
    .append("circle")
    .attr("r", 2.5)

  nodeWrapper = nodeWrapperEnter
    .merge(nodeWrapper).attr("class","merged");


  simulation
      .nodes(graph.nodes);

  simulation.force("link")
      .links(graph.links);
}

function ticked() {
    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; });

    nodeWrapper
        .attr("cx", function(d) { return d.x; })
        .attr("cy", function(d) { return d.y; });
}

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

这里有几个问题:

  1. 您的selectAll正在按元素类型nodeWrapper进行选择,您的意思是按课程.nodeWrapper
  2. 您将班级名称更改为&#34;合并&#34;在.merge之后,您无法执行此操作,因为它会在.nodeWrapper课程中打破未来的选择。
  3. 当您.merge选择时,您正在将circleg合并。您应保持一致并仅在g上操作。
  4. 快速重构:

    function update() {
    
      link = allLinkG
        .selectAll("line")
        .data(graph.links, function(d) {
          return d.id
        })
    
      link.exit().remove()
    
      linkEnter = link
        .enter().append("line");
    
      link = linkEnter.merge(link).attr("class", "merged");
    
      nodeWrapper = allNodeG
        .selectAll(".nodeWrapper") //<-- class nodeWrapper
        .data(graph.nodes, function(d) {
          return d.id;
        })
    
      nodeWrapperEnter = nodeWrapper.enter()
        .append("g").attr("class", "nodeWrapper"); //<-- enter selection should be gs
    
      nodeWrapperEnter //<-- append  your circles
        .append("circle")
        .attr("r", 2.5)
    
      nodeWrapper = nodeWrapperEnter //<-- merge, don't change class
        .merge(nodeWrapper);
    
      nodeWrapper.exit().remove();  //<-- and the exit
    
      simulation
        .nodes(graph.nodes);
    
      simulation.force("link")
        .links(graph.links);
    }
    

    注意,我还修改了您的tick功能,以便对g而不是circle进行操作:

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

    完整代码为here