سؤال

With the Mobile Patent Suit example by Mike Bostock as an example, I was able to re-create using my own data, but I want to take it a step further and dynamically update the node relationships on a drop-down change. The code works almost every time, but occasionally I get a single node with no relationships (see image below) even though data are available. I think I may be doing something wrong when clearing and then updating the nodes on a selection change, but it's strange to me that is works some of the time. Any help is greatly appreciated.

http://jsfiddle.net/calanoue/r6BRr/

var selectedCode = '0';

function updateNodes() {
   // Update the links and the nodes any time the data changes
   svg.selectAll('g').remove();

   links = allData[0][selectedCode];

   // Compute the distinct nodes from the links.
   links.forEach(function (link) {
    link.source = nodes[link.source] || (nodes[link.source] = {name: link.source});
    link.target = nodes[link.target] || (nodes[link.target] = {name: link.target});
   });

   force = d3.layout.force()
        .nodes(d3.values(nodes))
        .links(links)
        .size([width, height])
        .linkDistance(80)
        .charge(-400)
        .on("tick", tick)
        .start();

   path = svg.append("g").selectAll("path")
        .data(force.links())
        .enter().append("path")
        .attr("class", "link relationship")
        .attr("marker-end", "url(#relationship)");

   circle = svg.append("g").selectAll("circle")
        .data(force.nodes())
        .enter().append("circle")
        .attr('class', "generic")
        .attr("r", 8)
        .call(force.drag);
}

function tick() {
   // Use elliptical arc path segments to doubly-encode directionality.
   path.attr("d", linkArc);
   circle.attr("transform", transform);
}

function linkArc(d) {
   var dx = d.target.x - d.source.x,
        dy = d.target.y - d.source.y,
        dr = Math.sqrt(dx * dx + dy * dy);
   return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
}

function transform(d) {
   return "translate(" + d.x + "," + d.y + ")";
}

function clearNodes() {
   nodes = {};
   links = [];
   force.start();
   d3.timer(force.resume);
}

function codeChange() {
   selectedCode = this.value;
   clearNodes();
   updateNodes();
}

Missing Node Relationship Image:

missing node relationships

هل كانت مفيدة؟

المحلول

The problem you were having is that your original data, allData, was being changed by the computation of links and nodes at each data change iteration. After all, you set links = cloneData[0][selectedCode];. You need to clone allData before each data change.

function codeChange() {
    selectedCode = this.value;
    cloneData = clone(allData); // added
    clearNodes();
    updateNodes();
}

Here is a FIDDLE with all the changes to make it work. I borrowed the clone function from this SO question.

NOTE: I also removed one of your dropdown choices since you only have 3 sets of data in allData. That was not the cause of your problems, per above, but it was throwing errors whenever you selected the inexistent set.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top