简体   繁体   中英

d3js Force Layout Not Working As Expected

I've been working on a D3JS force layout graph, that isn't quite working as expected.

I've uploaded my code to JSFiddle, and can be seen here:

http://jsfiddle.net/jonaths/e9L3aq4k/

I think the important part of it is the following, that deals with updating the threshold of the nodes / links:

function threshold(thresh) {

    graph.links.splice(0, graph.links.length);

    for (var i = 0; i < graphRec.links.length; i++) {
        if (graphRec.links[i].value > thresh) {
            graph.links.push(graphRec.links[i]);
        }
    }

    graph.nodes.splice(0, graph.nodes.length);
    for (var j = 0; j < graphRec.nodes.length; j++) {
        if (graphRec.nodes[j].value > thresh) {
            graph.nodes.push(graphRec.nodes[j]);
        }
    }

    restart();
}


//Restart the visualisation after any node and link changes

function restart() {
    node = node.data(graph.nodes);
    link = link.data(graph.links);
    link.exit().remove();
    node.exit().remove();
    node.enter().insert("circle", ".node").attr("class", "node").attr("r", function (d) {
        return d.value / 5
    }).style("fill", "steelblue").call(force.drag);
    link.enter().insert("line", ".node").attr("class", "link").call(force.drag);
    force.start();
}

The idea is that as the threshold is increased, nodes and links that don't meet that threshold are removed. When the threshold is subsequently updated, additional links / nodes should be added / removed accordingly.

I used the code here as the basis for what I'm trying to do, but had to amend it to get the nodes to disappear, so there may well be an issue with my code.

Now what I'm finding, is that if you increase the threshold slowly, then it works perfectly. However, if you just click the threshold on to a high value, and then subsequently change it again, there is some weird behaviour that results in the graph breaking. You may notice the nodes collect in the top left. Reviewing outputs in the console shows the following error message:

Uncaught TypeError: Cannot read property 'weight' of undefined

But I can't for the life of me work out why that's happening sometimes, but not every time. I'm fairly new to D3, so any help & advice would be greatly appreciated, and I hope that I've provided all the required information for someone to give me some pointers. Thanks!

If you inspect your data when the error condition occurs, you are losing a source reference in a link to one of the nodes (it goes undefined):

[Object]
 0: Object
   source: undefined
   target: Object
   value: 75
   __proto__: Object
 length: 1
 __proto__: Array[0]

I'm not sure why, but I rewrote your threshold function to work on the d3 link and nodes objects (instead of going back to source json) and it behaves as expected:

var masterNodes = graph.nodes;
var masterLinks = graph.links;
function threshold(thresh) {
    graph.nodes = [];
    masterNodes.forEach(function(d,i){
        if (d.value > thresh){
            graph.nodes.push(d);
        }
    });         
    graph.links = [];
    masterLinks.forEach(function(d,i){
        if (d.value > thresh){
            graph.links.push(d);
        }
    });    
    restart();
}

Updated fiddle .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM