0

I'm using D3JS for building a force-directed graph. In a pre-version, I can for example make a 1200 nodes and 3717 links graph without any problem of performance. But in a clean version of my script, a 580 nodes and 649 links graph is very very slow.

In the first version, the creation of the graph and the style of nodes and links are made in the same time. In the second version version, I need to modify dynamically the style of nodes, for example hiding little nodes when zoom is out or when I click on a button. For doing this, I separate my script in 4 functions :

  • Choice of nodes and links to use in the force-system
  • Start of the force system
  • Choice of nodes to show
  • Style of nodes to show

With this, I have to case : I add or remove nodes so I call all the functions OR I zoom in or out so I call the last two to change only what the user see.

Is it possible that this separation is the cause of the lack of performance ? I don't think so because problems occur when all of these functions are over, when the tick function is running. But it's the only change between the two versions.

Thanks in advance for your help, and sorry for the poor English !

Edit 1 : The code

Choice of nodes and links to use in the force-system

function choiceNodesToUseForForce(){
//First we clean previous selection
for(itCN1=0;itCN1<nodesUnDisplayed.length;itCN1++){
    nodesUnDisplayed[itCN1].isUsed = false;
}
for(itCN1=0;itCN1<linksUnDisplayed.length;itCN1++){
    linksUnDisplayed[itCN1].isUsed = false;
}
usedLinks = new Array();
usedNodes = new Array();

for(itCNAU1=0;itCNAU1<linksUnDisplayed.length;itCNAU1++){
    lien = linksUnDisplayed[itCNAU1];
    //We used a link if one of his nodes is open (=focused)
    if((lien.source.isFocused || lien.target.isFocused) && lien.time <= time[1] && lien.time >= time[0] && !lien.isUsed){
        usedLinks.push(lien);
        lien.isUsed = true;
        if(!lien.source.isUsed){
            usedNodes.push(lien.source);
            lien.source.isUsed = true;
        }
        if(!lien.target.isUsed){
            usedNodes.push(lien.target);
            lien.target.isUsed = true;
        }
    }
  }
}

Starting the force-system

function startingForce(){
force.stop();
force.nodes(usedNodes).links(usedLinks);
force.start();
}

Choice of nodes to show

function choiceNodesToShow(){
//First we clean the previous selection
for(itCN1=0;itCN1<nodesUnDisplayed.length;itCN1++){
    nodesUnDisplayed[itCN1].isDisplayed = false;
}
for(itCN1=0;itCN1<linksUnDisplayed.length;itCN1++){
    linksUnDisplayed[itCN1].isDisplayed = false;
}

showedNodes = new Array();
showedLinks = new Array();

for(itCN1=0;itCN1<usedLinks.length;itCN1++){
    lien = liensUtilises[itCN1];
    //We show a link if : his two nodes are displayed
    if(lien.source.size > sizeLimite && lien.target.size > sizeLimite && !lien.isDisplayed){
        liensAAfficher.push(lien);
        //Add of nodes
        if(!lien.source.isDisplayed){
            showedNodes.push(lien.source);
            lien.source.isDisplayed = true;
        }
        if(!lien.target.isDisplayed){
            showedNodes.push(lien.target);
            lien.target.isDisplayed = true;
        }
     }
  }
}

Style of nodes to show

function styleNoeudsAAfficher(){
d3.selectAll('.node').remove();
d3.selectAll('.link').remove();
link = svg.selectAll('.link');
node = svg.selectAll('.node');

node = node.data(showedNodes, function(d){ return d.name;});
if(mode == "normal"){
    user.enter().append("circle") //Idem lien
        .attr("class", function(d) {return "node "+d.id+d.name;})
        .attr("r", function(d){ return d.size;})
        .attr("cx", function(d) {return d.x; })
        .attr("cy", function(d) { return d.y; })
        .attr("x", function(d) { return d.x-d.size/2; })
        .attr("y", function(d) { return d.y-d.size/2; })
        .attr("fill", function(d){return color(d.community);})
        .style("stroke-width", 1)
        .style("stroke", "black")
        .style("cursor", "pointer")
        .on("click", function(d){ clicNode(d);})
        .call(force.drag)
        .append("title")
            .text(function(d){return d.name;});


user.exit().remove();

link = link.data(showedLinks, function(d) { return d.sourceId + "-" + d.targetId; });

link.enter().insert("line", ".node")
    .attr("class", "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; })
    .style("stroke-width", 1)
    .style("stroke", "#848484")
    .append("title")
        .text(function(d){return d.source.name+" - "+d.target.name;})
link.exit().remove(); //On supprime les liens qui ont disparus
}
4

0 回答 0