代码之家  ›  专栏  ›  技术社区  ›  thatOneGuy

径向力布局的节点仅占圆的四分之一

  •  1
  • thatOneGuy  · 技术社区  · 7 年前

    我在单击按钮时实现了布局更改,使其从默认的强制布局变为径向布局: https://jsfiddle.net/mvLf579a/278/

    以下是更新代码:

    function radial() {
      simulation
        .force("charge", d3.forceCollide().radius(10))
        .force("r", d3.forceRadial(function(d) { 
          if (d.id < 5) {
            console.log('less than : ', d.id)
            return 100;
          } else {
            console.log('more than : ', d.id)
            return 300;
          } 
        }))
        .force("center", null)
        .on("tick", newTicked);
      simulation.alphaTarget(0.3).restart()
    
      function newTicked() {
        node
          .attr("transform", function(d) {
            return "translate(" + d.x + ", " + d.y + ")";
          });
      }
    }
    

    结果如下: enter image description here

    1 回复  |  直到 7 年前
        1
  •  1
  •   Gerardo Furtado    7 年前

    首先,传球 null 事实上,力会把它移走。这个 API 很清楚:

    无效的 作为原力。

    如果我对你的问题理解正确的话,你只要通过考试就可以解决它 x 和 y 中心的径向力,接受他们。这样地:

    .force("r", d3.forceRadial(function(d) {
        if (d.id < 5) {
            return 100;
        } else {
            return 300;
        }
    }, width / 2, height / 2))
    

    另外,为了获得更好的效果,设置 strength(1) 或者类似的高值。最后,使用 alpha 重新加热原力,而不是 alphaTarget

    下面是包含这些更改的代码(以及较小的SVG):

    function radial() {
      simulation
        .force("charge", d3.forceCollide().radius(10))
        .force("r", d3.forceRadial(function(d) {
          //console.log(d)
          if (d.id < 5) {
            return 100;
          } else {
            return 300;
          }
          //return d.id < 5 ? 100 : 200;
        }, width / 2, height / 2).strength(1))
        .force("center", null)
        .on("tick", newTicked);
      simulation.alpha(1).restart()
    
      function newTicked() {
        //node
        //   .attr("cx", function(d) { return d.x; })
        //  .attr("cy", function(d) { return d.y; });
        node
          .attr("transform", function(d) {
            return "translate(" + d.x + ", " + d.y + ")";
          });
      }
    
    }
    
    document.getElementById("radial").addEventListener("click", radial);
    
    var nodes = [{
        "id": 1,
        "name": "server 1"
      },
      {
        "id": 2,
        "name": "server 2"
      },
      {
        "id": 3,
        "name": "server 3"
      },
      {
        "id": 4,
        "name": "server 4"
      },
      {
        "id": 5,
        "name": "server 5"
      },
      {
        "id": 6,
        "name": "server 6"
      },
      {
        "id": 7,
        "name": "server 7"
      },
      {
        "id": 8,
        "name": "server 8"
      },
      {
        "id": 9,
        "name": "server 9"
      },
      {
        "id": 2,
        "name": "server 2"
      },
      {
        "id": 3,
        "name": "server 3"
      },
      {
        "id": 4,
        "name": "server 4"
      },
      {
        "id": 5,
        "name": "server 5"
      },
      {
        "id": 6,
        "name": "server 6"
      },
      {
        "id": 7,
        "name": "server 7"
      },
      {
        "id": 8,
        "name": "server 8"
      },
      {
        "id": 9,
        "name": "server 9"
      },
      {
        "id": 2,
        "name": "server 2"
      },
      {
        "id": 3,
        "name": "server 3"
      },
      {
        "id": 4,
        "name": "server 4"
      },
      {
        "id": 5,
        "name": "server 5"
      },
      {
        "id": 6,
        "name": "server 6"
      },
      {
        "id": 7,
        "name": "server 7"
      },
      {
        "id": 8,
        "name": "server 8"
      },
      {
        "id": 9,
        "name": "server 9"
      },
      {
        "id": 2,
        "name": "server 2"
      },
      {
        "id": 3,
        "name": "server 3"
      },
      {
        "id": 4,
        "name": "server 4"
      },
      {
        "id": 5,
        "name": "server 5"
      },
      {
        "id": 6,
        "name": "server 6"
      },
      {
        "id": 7,
        "name": "server 7"
      },
      {
        "id": 8,
        "name": "server 8"
      },
      {
        "id": 9,
        "name": "server 9"
      },
      {
        "id": 2,
        "name": "server 2"
      },
      {
        "id": 3,
        "name": "server 3"
      },
      {
        "id": 4,
        "name": "server 4"
      },
      {
        "id": 5,
        "name": "server 5"
      },
      {
        "id": 6,
        "name": "server 6"
      },
      {
        "id": 7,
        "name": "server 7"
      },
      {
        "id": 8,
        "name": "server 8"
      },
      {
        "id": 9,
        "name": "server 9"
      },
      {
        "id": 2,
        "name": "server 2"
      },
      {
        "id": 3,
        "name": "server 3"
      },
      {
        "id": 4,
        "name": "server 4"
      },
      {
        "id": 5,
        "name": "server 5"
      },
      {
        "id": 6,
        "name": "server 6"
      },
      {
        "id": 7,
        "name": "server 7"
      },
      {
        "id": 8,
        "name": "server 8"
      },
      {
        "id": 9,
        "name": "server 9"
      },
      {
        "id": 2,
        "name": "server 2"
      },
      {
        "id": 3,
        "name": "server 3"
      },
      {
        "id": 4,
        "name": "server 4"
      },
      {
        "id": 5,
        "name": "server 5"
      },
      {
        "id": 6,
        "name": "server 6"
      },
      {
        "id": 7,
        "name": "server 7"
      },
      {
        "id": 8,
        "name": "server 8"
      },
      {
        "id": 9,
        "name": "server 9"
      },
      {
        "id": 2,
        "name": "server 2"
      },
      {
        "id": 3,
        "name": "server 3"
      },
      {
        "id": 4,
        "name": "server 4"
      },
      {
        "id": 5,
        "name": "server 5"
      },
      {
        "id": 6,
        "name": "server 6"
      },
      {
        "id": 7,
        "name": "server 7"
      },
      {
        "id": 8,
        "name": "server 8"
      },
      {
        "id": 9,
        "name": "server 9"
      }
    ]
    
    var links = [{
        source: 1,
        target: 2
      },
      {
        source: 1,
        target: 3
      },
      {
        source: 1,
        target: 4
      },
      {
        source: 2,
        target: 5
      },
      {
        source: 2,
        target: 6
      },
      {
        source: 3,
        target: 7
      },
      {
        source: 5,
        target: 8
      },
      {
        source: 6,
        target: 9
      },
    ]
    
    var index = 10;
    var svg = d3.select("svg"),
      width = +svg.attr("width"),
      height = +svg.attr("height"),
      node,
      link;
    
    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));
    
    update();
    
    function update() {
      link = svg.selectAll(".link")
        .data(links, function(d) {
          return d.target.id;
        })
    
      link = link.enter()
        .append("line")
        .attr("class", "link");
    
      node = svg.selectAll(".node")
        .data(nodes, function(d) {
          return d.id;
        })
    
      node = node.enter()
        .append("g")
        .attr("class", "node")
        .on("click", click)
        .call(d3.drag()
          .on("start", dragstarted)
          .on("drag", dragged)
          .on("end", dragended));
    
      node.append("circle")
        .attr("r", 5)
    
      node.append("title")
        .text(function(d) {
          return d.id;
        });
    
    
      simulation
        .nodes(nodes)
        .on("tick", ticked);
    
      simulation.force("link")
        .links(links);
    }
    
    function click(d) {
      nodes.push({
        id: index,
        name: "server " + index
      });
      links.push({
        source: d.id,
        target: index
      });
      index++;
      update();
    }
    
    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;
        });
    
      node
        .attr("transform", function(d) {
          return "translate(" + d.x + ", " + d.y + ")";
        });
    }
    
    function dragstarted(d) {
      if (!d3.event.active) simulation.alphaTarget(0.3).restart()
    }
    
    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 = undefined;
      d.fy = undefined;
    }
    
    
    
    /*
    var nodes = [].concat(
      d3.range(80).map(function() { return {type: "a"}; }),
      d3.range(160).map(function() { return {type: "b"}; })
    );
    
    var node = d3.select("svg")
      .append("g")
      .selectAll("circle")
      .data(nodes)
      .enter().append("circle")
        .attr("r", 2.5)
        .attr("fill", function(d) { return d.type === "a" ? "brown" : "steelblue"; })
    
    var simulation = d3.forceSimulation(nodes)
        .force("charge", d3.forceCollide().radius(5))
        .force("r", d3.forceRadial(function(d) { return d.type === "a" ? 100 : 200; }))
        .on("tick", ticked);
    
    function ticked() {
      node
          .attr("cx", function(d) { return d.x; })
          .attr("cy", function(d) { return d.y; });
    }
    */
    .link {
      stroke: #aaa;
    }
    
    .node {
      pointer-events: all;
      stroke: none;
      stroke-width: 40px;
    }
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <button id='radial'>
     Radial
    </button>
    <svg width="500" height="400" viewBox="-240 -125 960 500">