javascript - 与 D3.js 交互作用力

标签 javascript d3.js physics gravity force-layout

我正在尝试“模拟”粒子向“焦点”移动时的引力。实际上,我正在尝试修改以下代码,以便粒子在前往蓝色节点的途中被橙色节点稍微偏离轨道。我的问题是我无法使用 D3.js 强制定向布局来概念化它。我意识到这是一个非常模糊的问题,但非常感谢任何帮助!图片和代码如下:

enter image description here

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <title>Force Layouts - Quantitative Foci</title>
    <script type="text/javascript" src="http://d3js.org/d3.v2.min.js?2.8.1"></script>
    <style type="text/css">

circle {
  stroke: #fff;
}

svg {
  fill: #fff;
  stroke: #000;
}

    </style>
  </head>
  <body>
    <div id="body">
      <div id="chart"></div>
    </div>
    <script type="text/javascript">

var w = 1280,
    h = 800,
    color = d3.scale.category10();

var force = d3.layout.force()
    .gravity(0)
    .charge(-5)
    .linkStrength(0)
    .size([w, h]);

var links = force.links(),
    nodes = force.nodes(),
    centers = [
      {type: 0, x: 3 * w / 6, y: 2 * h / 6, fixed: true},
      {type: 1, x: 4 * w / 6, y: 4 * h / 6, fixed: true}
    ];

var svg = d3.select("#chart").append("svg:svg")
    .attr("width", w)
    .attr("height", h);

svg.append("svg:rect")
    .attr("width", w)
    .attr("height", h);

svg.selectAll("circle")
    .data(centers)
  .enter().append("svg:circle")
    .attr("r", 12)
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .style("fill", fill)
    .call(force.drag);

force.on("tick", function(e) {
  var k = e.alpha * .1;
  nodes.forEach(function(node) {
    var center = centers[node.type];
    node.x += (center.x - node.x) * k;
    node.y += (center.y - node.y) * k;
  });

  svg.selectAll("circle")
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; });

  svg.selectAll("line")
      .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; });
});

var p0;

svg.on("mousemove", function() {
  var p1 = d3.svg.mouse(this),
      a = {type: 0, x: p1[0], y: p1[1], px: (p0 || (p0 = p1))[0], py: p0[1]},
      b = {type: 1, x: centers[1].x, y: centers[1].y, fixed:true},
      link = {source: a, target: b};

  p0 = p1;

  svg.selectAll()
      .data([a, b])
    .enter().append("svg:circle")
      .attr("cx", function(d) { return d.x; })
      .attr("cy", function(d) { return d.y; })
      .attr("r", 4.5)
      .style("fill", fill)
    .transition()
      .delay(3000)
      .attr("r", 1e-6)
      .remove();

  svg.insert("svg:line", "circle")
      .data([link])
    .transition()
      .delay(3000)
      .each("end", function() {
        nodes.splice(nodes.indexOf(a), 1);
        nodes.splice(nodes.indexOf(b), 1);
        links.splice(links.indexOf(link), 1);
      })
      .remove();

  nodes.push(a, b);
  links.push(link);
  force.start();
});

function fill(d) {
  return color(d.type);
}

    </script>
  </body>
</html>

1 http://jsfiddle.net/fbW7T/1/ -- 之前。

[2] http://jsfiddle.net/fbW7T/2/ -- 之后,在 Lephix 的提议下。

最佳答案

首先,你的问题很有趣:)。
用以下代码替换您的 force.on("tick", function(e) {...}) 。其实我只是在函数中添加了一个变量和10行代码。
fr 表示粒子应该偏离橙色节点的圆形区域的半径。

var fr = 100;
force.on("tick", function(e) {
  var k = e.alpha * .1;
  nodes.forEach(function(node) {
  var center = centers[node.type];
  node.x += (center.x - node.x) * k;
  node.y += (center.y - node.y) * k;

if (node.type == 0) {
    center = centers[1];
    while (Math.abs(node.x - center.x) < fr && Math.abs(node.y - center.y) < fr) {
        if (Math.abs(node.x - center.x) >= Math.abs(node.y - center.y)) {
            node.x += (node.x - center.x)/Math.abs(node.x - center.x);
        } else {
            node.y += (node.y - center.y)/Math.abs(node.y - center.y);
        }
    }
}
});

svg.selectAll("circle")
  .attr("cx", function(d) { return d.x; })
  .attr("cy", function(d) { return d.y; });

svg.selectAll("line")
  .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; });
});

关于javascript - 与 D3.js 交互作用力,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11040527/

相关文章:

javascript - 文本效果在 jquery 中无法正确循环

d3.js - 是否可以在D3的标签云中使用点击事件,如果可以,如何使用?

lua - 宇宙飞船的二维轨迹规划与物理

C++:洛伦兹因子方程

javascript - 使用百分比值更新进度条?

javascript - Ajax 发送功能不会触发?

javascript - 如何重用对象文字

google-chrome - d3 滚动缩放在 Chrome 上不再起作用

javascript - D3 节点的标签和图像错误地显示在屏幕的左上角

java - n-body Simulation 预期性能 barnes hut