簡體   English   中英

更新D3力圖-如何刪除圓和文字?

[英]Update D3 Force chart - how to remove Circles & Text?

我使用Angular 6和D3v4創建了一個力模擬圖,並且第一次加載就很好,並且我向圓圈和文本添加了一個click事件來更新數據,但是過渡效果很奇怪-有些節點在已刪除,但其余節點僅添加了一個新的圓圈和文本...我嘗試了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").selectAll(".link"); this.node = this.g.append("g").selectAll(".node"); this.link = this.g.append("g").selectAll(".link"); this.node = this.g.append("g").selectAll(".node");

createGraphupdateGraph現在我調用一個方法makeNodes() -的秘密武器是this.svg.selectAll('g .node').remove(); this.svg.selectAll('g text').remove(); this.svg.selectAll('g .node').remove(); this.svg.selectAll('g text').remove();

然后我可以干凈地添加我的節點...

希望這對其他嘗試此模式的人有所幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM