Javascript 更新D3力图-如何删除圆圈和;文本?

Javascript 更新D3力图-如何删除圆圈和;文本?,javascript,d3.js,angular5,Javascript,D3.js,Angular5,我正在使用Angular 6和D3v4创建一个力模拟图表,它第一次加载就很好,我在圆圈和文本中添加了一个单击事件来更新数据,但是转换工作异常-一些节点被删除,但其余节点只添加了一个新的圆圈和文本。。。我试过Mike Bostock的,但在Angular(或者可能是D3的新版本?)中,这似乎对我不起作用。。。以下是我正在做的: ngOnInit() { // get data from service this.service.getGraphData(this.id).subsc

我正在使用Angular 6和D3v4创建一个力模拟图表,它第一次加载就很好,我在圆圈和文本中添加了一个单击事件来更新数据,但是转换工作异常-一些节点被删除,但其余节点只添加了一个新的圆圈和文本。。。我试过Mike Bostock的,但在Angular(或者可能是D3的新版本?)中,这似乎对我不起作用。。。以下是我正在做的:

ngOnInit() {
    // get data from service
    this.service.getGraphData(this.id).subscribe(results => {
        this.graphData = results;
        this.forceSimulation = d3.forceSimulation(this.graphData)
    // push nodes apart to space them out
      .force("charge", d3.forceManyBody().strength(-100))
      // add some collision detection so they don't overlap
      .force("collide", d3.forceCollide().radius(55))
      // and draw them around the centre of the space
      .force("center", d3.forceCenter(this.width / 2, this.height / 2));

    this.link = this.svg.selectAll(".link").data(this.graphData.links)
      .enter()
      .append("path")
      .attr("class", "link")
      .attr('stroke', "#FFF");

    this.node = this.svg.selectAll(".node")
      .data(this.graphData.nodes)
      .enter()
      .append('g');

    this.updateGraph();
  });
}

updateGraph() {
    let graphComponent = this;

    //start building/rebuilding the graph
    let t = d3.transition().duration(750);

    this.link = this.link.data(this.graphData.links);
    this.link.exit().remove();

    this.forceSimulation
    // pull nodes together based on the links between them
      .force("link", d3.forceLink().id(function (d) {
          return d.id;
      }).strength(0.025));

    // add the nodes to the graphic
    this.node = this.node.data(this.graphData.nodes);

    this.node.exit().remove();

    this.node.transition(t).style('fill', 'blue').attr('35');

    this.node.append("circle")
      .attr("class", "node")
      .attr("r", function (d) {
        // center node = larger & blue
        return d.id == graphComponent.programNode.id ? 65 : 40;
      })
      .attr('stroke', function (d) {
        // apply red border to nodes
        return 'red';
      })
      .attr('stroke-width', function (d) {
        return d.id == graphComponent.programNode.id ? 0 : 3;
      })
      .attr("fill", function (d) {
        return d.id == graphComponent.programNode.id ? 'blue' : '#FFF';
      })
      .on('click', function (d) {
        if (d.id !== graphComponent.programNode.id) {
          graphComponent.currentLevel++;
          graphComponent.componentClicked(d.programId);
        }
      });

    // add a label to each node
    this.node.append("text")
      .attr('x', 0)
      .attr('y', function (d) {
        return d.name.length > 10 ? -20 : 0;
      })
      .attr('text-anchor', 'middle')
      .attr("dy", "0").merge(this.node)
      .text(function (d) {
        return d.name.replace(/\w\S*/g, function (txt) {
          return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
        });
      })
      .style("stroke", function (d) {
        return d.id == graphComponent.programNode.id ? 'white' : 'black'
      })
      .style("stroke-width", .70)
      .style("fill", function (d) {
        return d.id == graphComponent.programNode.id ? '#FFF' : '#000';
      })
      .call(graphComponent.wrap, 35) // fit text inside of node circle
      .on('click', function (d) {
        if (d.programId !== graphComponent.programNode.id) {
          graphComponent.currentLevel++;
          graphComponent.componentClicked(d.programId);
        }
      });


    // Update and restart the simulation.
    this.forceSimulation.nodes(this.graphData.nodes)
      .force("collide", d3.forceCollide().strength(1).radius(55).iterations(1))
      .on("tick", ticked);

    this.forceSimulation
      .force("link")
      .links(this.graphData.links);

    // on each tick, update node and link positions
    // draws links and moves nodes' x & y positions inside the svg
    function ticked() {
      graphComponent.link.attr('d', graphComponent.positionLink);
      graphComponent.node.attr("transform", graphComponent.positionNode);
    }
}
所以。。。更新之后,我最终得到了

    <g transform="translate(..., ...)>
        <circle class="node" ...></circle>
        <text ...>First call's text</text>
        <circle class="node" ...></circle>
        <text ...>Second call's text</text>
    </g>

发现这是所有事情的时间安排。。。因此,在init中简化到该节点/链接:
this.link=this.g.append(“g”)。选择全部(“link”);
this.node=this.g.append(“g”)。选择所有(“.node”)

createGraph
updateGraph
中,我现在调用一个方法
makeNodes()
——秘方是
this.svg.selectAll('g.node').remove();
this.svg.selectAll('g text').remove()

然后我可以干净地添加我的节点

希望这能帮助其他尝试这种模式的人