同时移动所有节点包括链接?

时间:2017-07-04 23:40:31

标签: javascript d3.js nodes force-layout

在D3.js中的

我使用force-layout将所有节点向右移动,使用下面的代码。但是当调用函数时,只有节点移位,文本和链接保持不变。究竟缺少什么?是否必须在函数内调用tick()函数?

  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);

              });

2 个答案:

答案 0 :(得分:2)

您的函数仅移动包含节点的g。它不会更新附加到节点的基础数据(d.x和d.y)。因此,虽然它们在视觉上移动,但它不是因为力(或您的代码)更新了d.x或d.y值。

答案 1 :(得分:1)

正如@TomShanley在his answer中所说,你只是在翻译包含<g>个元素。

不要这样做。将节点移动到固定位置的惯用方法是设置fxfy,或者使用forceYforceY(均在D3 v4中)。

这是使用forceX的演示。首先,我们移除center力,然后将forceX设置为右侧的位置:

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

这是演示,单击按钮移动节点,链接和文本:

&#13;
&#13;
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 d.r + 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 d.r = 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 d.x
  }).attr("cy", function(d) {
    return d.y
  });

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

});

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

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();
})
&#13;
<script src="https://d3js.org/d3.v4.js"></script>
<button>Click me</button>
<br>
&#13;
&#13;
&#13;