i trying update data force simulation in d3 v4, similar this unsuccessful attempt , semi-similar this successful one. codepen here
instead of joining new nodes appears doubling nodes (see pictures). not seem refreshing graph correctly either.
html:
<button onclick="adddata()">add data</button> <svg width="960" height="600"></svg>
javascript:
function adddata() { graph.nodes.push({"id": "extra1", "group": 11},{"id": "extra2", "group": 11}) graph.links.push({"source": "extra1", "target": "valjean", "strength": 1},{"source": "extra1", "target": "extra2", "strength": 2}) update() simulation.restart() } var svg = d3.select("svg"), width = +svg.attr("width"), height = +svg.attr("height"); var link, linkenter, nodewrapper, nodewrapperenter; var simulation = d3.forcesimulation() .force("link", d3.forcelink().id(function(d) { return d.id; })) .force("charge", d3.forcemanybody()) .force("center", d3.forcecenter(width / 2, height / 2)) .on("tick", ticked); var alllinkg = svg.append("g") .attr("class", "alllinkg") var allnodeg = svg.append("g") .attr("class", "allnodeg") update() simulation.restart() function update(){ link = alllinkg .selectall("line") .data(graph.links, function(d){ return d.id }) link.exit().remove() linkenter = link .enter().append("line"); link = linkenter.merge(link).attr("class","merged"); nodewrapper = allnodeg .selectall("nodewrapper") .data(graph.nodes, function(d) { return d.id; }) nodewrapper.exit().remove(); nodewrapperenter = nodewrapper.enter() .append("g").attr("class","nodewrapper") .append("circle") .attr("r", 2.5) nodewrapper = nodewrapperenter .merge(nodewrapper).attr("class","merged"); simulation .nodes(graph.nodes); simulation.force("link") .links(graph.links); } function ticked() { 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; }); nodewrapper .attr("cx", function(d) { return d.x; }) .attr("cy", function(d) { return d.y; }); }
thanks help.
a few issues here:
- your
selectall
selecting element typenodewrapper
, meant class.nodewrapper
. - you change class name "merged" after
.merge
, can't breaks future selections.nodewrapper
class. - when
.merge
selection, mergingcircle
sg
s. should stay consistent , operate ong
s only.
quick refactor:
function update() { link = alllinkg .selectall("line") .data(graph.links, function(d) { return d.id }) link.exit().remove() linkenter = link .enter().append("line"); link = linkenter.merge(link).attr("class", "merged"); nodewrapper = allnodeg .selectall(".nodewrapper") //<-- class nodewrapper .data(graph.nodes, function(d) { return d.id; }) nodewrapperenter = nodewrapper.enter() .append("g").attr("class", "nodewrapper"); //<-- enter selection should gs nodewrapperenter //<-- append circles .append("circle") .attr("r", 2.5) nodewrapper = nodewrapperenter //<-- merge, don't change class .merge(nodewrapper); nodewrapper.exit().remove(); //<-- , exit simulation .nodes(graph.nodes); simulation.force("link") .links(graph.links); }
note, modified tick
function operate on g
instead of circle
:
nodewrapper .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
full code here.
Comments
Post a Comment