Adding nodes dynamically to D3 Force Layout in version 4

后端 未结 1 1185
伪装坚强ぢ
伪装坚强ぢ 2021-02-06 10:22

I am trying to implement a simple force layout in which nodes (without links) can be dynamically added and removed. I was successful in implementing the concept in D3 version 3,

相关标签:
1条回答
  • 2021-02-06 10:57

    Please see plunkr example

    I'm using canvas, but the theory is the same:

    You have to give your new array of nodes and links to D3 core functions first, before adding them to the original array.

    drawData: function(graph){
      var countExtent = d3.extent(graph.nodes,function(d){return d.connections}),
          radiusScale = d3.scalePow().exponent(2).domain(countExtent).range(this.nodes.sizeRange);
    
          // Let D3 figure out the forces
          for(var i=0,ii=graph.nodes.length;i<ii;i++) {
            var node = graph.nodes[i];
    
            node.r = radiusScale(node.connections);
            node.force = this.forceScale(node);
            };
    
        // Concat new and old data
        this.graph.nodes = this.graph.nodes.concat(graph.nodes);
        this.graph.links = this.graph.links.concat(graph.links);
    
        // Feed to simulation
        this.simulation
            .nodes(this.graph.nodes);
    
        this.simulation.force("link")
            .links(this.graph.links);
    
        this.simulation.alpha(0.3).restart();
    }
    

    Afterwards, tell D3 to restart with the new data.

    When D3 calls your tick() function, it already knows what coordinates you need to apply to your SVG elements.

    ticked: function(){
         if(!this.graph) {
            return false;
        }
    
        this.context.clearRect(0,0,this.width,this.height);
        this.context.save();
        this.context.translate(this.width / 2, this.height / 2);
    
        this.context.beginPath();
        this.graph.links.forEach((d)=>{
            this.context.moveTo(d.source.x, d.source.y);
            this.context.lineTo(d.target.x, d.target.y);
        });
        this.context.strokeStyle = this.lines.stroke.color;
        this.context.lineWidth = this.lines.stroke.thickness;
    
        this.context.stroke();
    
        this.graph.nodes.forEach((d)=>{
            this.context.beginPath();
    
            this.context.moveTo(d.x + d.r, d.y);
            this.context.arc(d.x, d.y, d.r, 0, 2 * Math.PI);
    
            this.context.fillStyle = d.colour;
            this.context.strokeStyle =this.nodes.stroke.color;
            this.context.lineWidth = this.nodes.stroke.thickness;
            this.context.fill();
            this.context.stroke();
        });
    
        this.context.restore();
    }
    

    Plunkr example

    0 讨论(0)
提交回复
热议问题