简体   繁体   中英

Moving all nodes the same time including links?

in D3.js I use the force-layout to shift all nodes to the right with this code below. But when call the function, only the nodes shift, the text and links stay the same. What exactly is missing here? Is it the tick() function that has to be called inside the function?

  function(){ d3.select(".nodes").attr("transform", "translate(200,0)");

                simulation.alpha(0.8).restart();


};

        simulation
                    .nodes(nodes)
                    .on("tick", function(d)
                    {

                      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("cx", function(d) { return d.x; })
                        .attr("cy", function(d) { return d.y; });

                     text
                        .attr("x", function(d) { return d.x; }) 
                        .attr("y", function(d) { return d.y; });



                    }

                    );

                simulation.force("link")
                    .links(links);

              });

Your function only moves the g that contains the nodes. It doesn't update the underlying data (dx and dy) that is attached to the nodes. So while they visually move, it isn't because the force (or your code) has updated the dx or dy values.

As @TomShanley said in his answer , you are only translating the containing <g> elements.

Don't do that. The idiomatic way to move the nodes for a fixed position is setting fx and fy or, alternatively, using forceY and forceY (both in D3 v4).

This is a demo using forceX . First, we remove the center force, then we set forceX to a position at the right:

simulation.force("center", null)
simulation.force("toRight", d3.forceX(360).strength(0.8))

Here is the demo, click the button to move the nodes, links and texts:

 var width = 400; var height = 300; var svg = d3.select("body") .append("svg") .attr("width", width) .attr("height", height); var nodes = [{ name: "foo", color: "blue" }, { name: "bar", color: "green" }, { name: "baz", color: "red" }, { name: "foofoo", color: "yellow" }, { name: "foobar", color: "blue" }, { name: "foobaz", color: "green" }, { name: "barfoo", color: "red" }, { name: "barbar", color: "yellow" }, { name: "barbaz", color: "blue" }]; var links = [{ "source": 0, "target": 1 }, { "source": 0, "target": 2 }, { "source": 0, "target": 3 }, { "source": 1, "target": 3 }, { "source": 1, "target": 4 }, { "source": 2, "target": 5 }, { "source": 3, "target": 6 }, { "source": 1, "target": 7 }, { "source": 6, "target": 8 }, { "source": 0, "target": 7 }, { "source": 2, "target": 6 }, { "source": 3, "target": 8 }]; var simulation = d3.forceSimulation() .force("link", d3.forceLink()) .force("charge", d3.forceManyBody().strength(-50)) .force("center", d3.forceCenter(width / 2, height / 2)) .force("collide", d3.forceCollide(function(d) { return dr + 1; })); var link = svg.selectAll(null) .data(links) .enter() .append("line") .style("stroke", "#ccc") .style("stroke-width", 1); var node = svg.selectAll(null) .data(nodes) .enter() .append("circle") .attr("r", function(d) { return dr = 10; }) .attr("stroke", "gray") .attr("stroke-width", "2px") .attr("fill", function(d) { return d.color }) .call(d3.drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended));; var text = svg.selectAll(null) .data(nodes) .enter() .append("text") .attr("pointer-events", "none") .style("fill", "black") .attr("dy", "-1em") .attr("dx", "-1em") .text(function(d) { return d.name; }); simulation.nodes(nodes); simulation.force("link") .links(links); simulation.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("cx", function(d) { return dx }).attr("cy", function(d) { return dy }); text.attr("x", function(d) { return dx }).attr("y", function(d) { return dy }); }); function dragstarted(d) { if (!d3.event.active) simulation.alphaTarget(0.3).restart(); d.fx = dx; d.fy = dy; } function dragged(d) { d.fx = d3.event.x; d.fy = d3.event.y; } function dragended(d) { if (!d3.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; } d3.select("button").on("click", function(d) { simulation.force("center", null) simulation.force("toRight", d3.forceX(360).strength(0.8)) simulation.alpha(0.8).restart(); }) 
 <script src="https://d3js.org/d3.v4.js"></script> <button>Click me</button> <br> 

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