In a d3 force simulation, is there a way to force away from certain fixed points?

Viewed 71

I want nodes to repel away from the edges of the svg. I've been fiddling with the strength of the links and the forceManyBody() strength, but any time I interact with a node with lots of links, it sends smaller node clusters off the screen. I want the nodes to separate evenly without being blasted off like a rocketship.

Here's what it looks like when I run the simulation without interacting with it:

enter image description here

And this is on a large svg (2400,1600) that will probably get reduced to half the size.

I'm thinking if I force away from the corners and the midpoint between each corner, they'll still separate, but won't get launched off the screen.

Here's the current force simulation code:

var force = d3
    .forceSimulation(data.nodes)
    .force(
      "link",
      d3
        .forceLink()
        .id(function (d) {
          return d.name;
        })
        .strength(0.4)
        .links(data.links)
    )
    .force("charge", d3.forceManyBody().strength(-20))
    .force("center", d3.forceCenter(1200, 800))
    .force(
      "collision",
      d3.forceCollide().radius((node) => {
        return node.type === "application" ? 50 : 30;
      })
    )
    .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 + ")";
      });
    });

So, is there a way to force nodes away from the edges, or a better way to achieve separation without losing nodes?

0 Answers
Related