释放所有粘性节点

问题描述 投票:3回答:1

如何修改以下example,以便在按下按钮时释放所有粘性节点?我已经看到这个实现了节点被双击(here)释放(unstuck),但我想同时释放它们(我的计划是将它包含在图的restart()函数中)。

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  .links line {
    stroke: #999;
    stroke-opacity: 0.6;
  }
  
  .nodes circle {
    stroke: #fff;
    stroke-width: 1.5px;
  }
</style>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
  //create somewhere to put the force directed graph
  var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");


  var nodes_data = [{
      "name": "Travis",
      "sex": "M"
    },
    {
      "name": "Rake",
      "sex": "M"
    },
    {
      "name": "Diana",
      "sex": "F"
    },
    {
      "name": "Rachel",
      "sex": "F"
    },
    {
      "name": "Shawn",
      "sex": "M"
    },
    {
      "name": "Emerald",
      "sex": "F"
    }
  ]
  var links_data = [{
      "source": "Travis",
      "target": "Rake"
    },
    {
      "source": "Diana",
      "target": "Rake"
    },
    {
      "source": "Diana",
      "target": "Rachel"
    },
    {
      "source": "Rachel",
      "target": "Rake"
    },
    {
      "source": "Rachel",
      "target": "Shawn"
    },
    {
      "source": "Emerald",
      "target": "Rachel"
    }
  ]
  //set up the simulation 
  var simulation = d3.forceSimulation()
    //add nodes
    .nodes(nodes_data);


  //add forces
  //we're going to add a charge to each node 
  //also going to add a centering force
  //and a link force
  var link_force = d3.forceLink(links_data)
    .id(function(d) {
      return d.name;
    });
  simulation
    .force("charge_force", d3.forceManyBody())
    .force("center_force", d3.forceCenter(width / 2, height / 2))
    .force("links", link_force);

  //add tick instructions: 
  simulation.on("tick", tickActions);
  //draw circles for the links 
  var node = svg.append("g")
    .attr("class", "nodes")
    .selectAll("circle")
    .data(nodes_data)
    .enter()
    .append("circle")
    .attr("r", 10)
    .attr("fill", "red");
  //draw lines for the links 
  var link = svg.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(links_data)
    .enter().append("line")
    .attr("stroke-width", 2);


  var drag_handler = d3.drag()
    .on("start", drag_start)
    .on("drag", drag_drag)
    .on("end", drag_end);

  //same as using .call on the node variable as in https://bl.ocks.org/mbostock/4062045 
  drag_handler(node)
  //drag handler
  //d is the node 
  function drag_start(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
  }

  function drag_drag(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
  }

  function drag_end(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
    d.fx = d.x;
    d.fy = d.y;
  }

  function tickActions() {
    //update circle positions each tick of the simulation 
    node
      .attr("cx", function(d) {
        return d.x;
      })
      .attr("cy", function(d) {
        return d.y;
      });

    //update link positions 
    //simply tells one end of the line to follow one node around
    //and the other end of the line to follow the other node around
    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;
      });
  }
</script>
d3.js graph force-layout
1个回答
4
投票

这不是Bostock的bl.ocks,并没有双击那里释放节点。

无论如何,您只需要删除fxfy属性,然后再次重新模拟仿真:

d3.select("button").on("click", function() {
    node.each(function(d) {
        d.fx = d.fy = null;
    })
    simulation.alphaTarget(0.3).restart();
})

我正在使用alphaTarget,因为这是你的代码中的内容,但你应该考虑使用alpha

以下是具有该更改的代码:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  .links line {
    stroke: #999;
    stroke-opacity: 0.6;
  }
  
  .nodes circle {
    stroke: #fff;
    stroke-width: 1.5px;
  }
</style>
<button>Release</button>
<svg width="600" height="400"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
  //create somewhere to put the force directed graph
  var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");


  var nodes_data = [{
      "name": "Travis",
      "sex": "M"
    },
    {
      "name": "Rake",
      "sex": "M"
    },
    {
      "name": "Diana",
      "sex": "F"
    },
    {
      "name": "Rachel",
      "sex": "F"
    },
    {
      "name": "Shawn",
      "sex": "M"
    },
    {
      "name": "Emerald",
      "sex": "F"
    }
  ]
  var links_data = [{
      "source": "Travis",
      "target": "Rake"
    },
    {
      "source": "Diana",
      "target": "Rake"
    },
    {
      "source": "Diana",
      "target": "Rachel"
    },
    {
      "source": "Rachel",
      "target": "Rake"
    },
    {
      "source": "Rachel",
      "target": "Shawn"
    },
    {
      "source": "Emerald",
      "target": "Rachel"
    }
  ]
  //set up the simulation 
  var simulation = d3.forceSimulation()
    //add nodes
    .nodes(nodes_data);


  //add forces
  //we're going to add a charge to each node 
  //also going to add a centering force
  //and a link force
  var link_force = d3.forceLink(links_data)
    .id(function(d) {
      return d.name;
    });
  simulation
    .force("charge_force", d3.forceManyBody())
    .force("center_force", d3.forceCenter(width / 2, height / 2))
    .force("links", link_force);

  //add tick instructions: 
  simulation.on("tick", tickActions);
  //draw circles for the links 
  var node = svg.append("g")
    .attr("class", "nodes")
    .selectAll("circle")
    .data(nodes_data)
    .enter()
    .append("circle")
    .attr("r", 10)
    .attr("fill", "red");
  //draw lines for the links 
  var link = svg.append("g")
    .attr("class", "links")
    .selectAll("line")
    .data(links_data)
    .enter().append("line")
    .attr("stroke-width", 2);


  var drag_handler = d3.drag()
    .on("start", drag_start)
    .on("drag", drag_drag)
    .on("end", drag_end);

  //same as using .call on the node variable as in https://bl.ocks.org/mbostock/4062045 
  drag_handler(node)
  //drag handler
  //d is the node 
  function drag_start(d) {
    if (!d3.event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
  }

  function drag_drag(d) {
    d.fx = d3.event.x;
    d.fy = d3.event.y;
  }

  function drag_end(d) {
    if (!d3.event.active) simulation.alphaTarget(0);
    d.fx = d.x;
    d.fy = d.y;
  }

  function tickActions() {
    //update circle positions each tick of the simulation 
    node
      .attr("cx", function(d) {
        return d.x;
      })
      .attr("cy", function(d) {
        return d.y;
      });

    //update link positions 
    //simply tells one end of the line to follow one node around
    //and the other end of the line to follow the other node around
    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;
      });
  }

  d3.select("button").on("click", function() {
    node.each(function(d) {
      d.fx = d.fy = null;
    })
    simulation.alphaTarget(0.3).restart();
  })
</script>
© www.soinside.com 2019 - 2024. All rights reserved.