javascript - D3.js: Attributes after enter().append() not setting -


like people, i'm struggling d3's data join mechanics. have read every article on subject, , (mostly) bad. christian behrens' guest-and-chair party analogy best, though warn readers neglects 2/3 through, beginning "now our update() function performs 2 different sets of actions" -- doesn't clarify here that, apparently, dom construction (append/remove) calls ignored update selection, while attribute calls processed 3 selection types, despite appearing seamlessly in 1 method chain. (for part, mike bostock's several efforts @ explaining data joins , method chaining range mildly condescending entirely complicating matters.)

i still have problem understanding membrane between data() , enter(), when save variable , how calls in given chain operate on objects, , chain return value variable saves, , how should know (clearly, attr not affect variable, in chain includes series of selects, data, , enters, returned?); hence mild criticism of otherwise excellent behrens essay, because has promise there.

below, have force layout (could layout) displays 2 nodes on startup, , if click of nodes, third should added.

var graph = {   "nodes":[ {"name":"1" }, {"name":"2" } ],   "links":[ {"source":0,"target":1} ] }  var width = 500, height = 400;  var force = d3.layout.force()   .size([width, height]);  var svg = d3.select("#map").append("svg")   .attr("width", width)   .attr("height", height)   .append("g")  var rect = svg.append("rect")   .attr("width", width)   .attr("height", height)   .style("fill", "none")   .style("pointer-events", "all");  var container = svg.append("g");  force   .nodes(graph.nodes)   .links(graph.links)   .start();  var link = container.append("g")   .attr("class", "links")   .selectall(".link")   .data(graph.links)   .enter()     .append("line")     .attr("class", "link")   .style("stroke-width", function(d) { return math.sqrt(d.value); });  var nodes = container.append("g")   .attr("class", "nodes");  function update() {    var n = nodes.selectall(".node").data(graph.nodes);    ne = n.enter()     .append("g")     .attr("class", "node")     .attr("cx", function(d) { return d.x; })  // sets on initial enter() not on click     .attr("cy", function(d) { return d.y; }); // sets on initial enter() not on click    ne.append("rect")     .attr("width", "20")     .attr("height", "20")     .attr("fill", "red");      return n;  } // end update()  var node = update();  force.on("tick", function() {   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; });   node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); });  node.on("click", function(d) {   graph.nodes.push({ "name":"3" });   update(); }); // end .on("click") 

i made update() function economize, following behrens. setting cx , cy works fine not when click on node. new nodes stay @ [0,0]. think there must problem in way manage arguments , returns on update(). better way this, 1 works?

you're missing 2 small things. first, need restart force layout node positions updated, , need update node you're using inside tick handler function:

node.on("click", function(d) {   graph.nodes.push({ "name":"3" });   node = update();   force.start(); }); 

complete demo here.


Comments

Post a Comment

Popular posts from this blog

Capture and play voice with Asterisk ARI -

python - How to use elasticsearch.helpers.streaming_bulk -