最近在看到d3.js实现力导向图中节点的拖拽功能时,用到了下面的代码:
function dragStarted(d) {
d.fx = d.x; // <-E
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x; // <-F
d.fy = d3.event.y;
}
function dragEnded(d) {
d.fx = null; // <-G
d.fy = null;
}
这几个函数使用时非常简单,如下:
newNodes.forEach(function (node) {
svg.append("circle")
.data([node])
.attr("class", "node")
.attr("cx", function (d) {return d.x;})
.attr("cy", function (d) {return d.y;})
.attr("r", 1e-6)
.call(d3.drag() // <-D
.on("start", dragStarted)
.on("drag", dragged)
.on("end", dragEnded))
.transition()
.attr("r", 7)
.transition()
.delay(duration)
.attr("r", 1e-6)
.on("end", function () {nodes.shift();})
.remove();
});
主要疑惑在于,上面自定义的几个函数中,d.fx, d.fy的意义是什么?在拖拽过程中是怎么起作用的呢?
原来,力模拟时,每一个节点是一个object,有这样几个属性(原文如下:https://github.com/d3/d3-force#simulation_nodes)
Each node must be an object. The following properties are assigned by the simulation:
index
- the node’s zero-based index into nodesx
- the node’s current x-positiony
- the node’s current y-positionvx
- the node’s current x-velocityvy
- the node’s current y-velocityTo fix a node in a given position, you may specify two additional properties:
fx
- the node’s fixed x-positionfy
- the node’s fixed y-positionAt the end of each tick, after the application of any forces, a node with a defined node.fx has node.x reset to this value and node.vx set to zero; likewise, a node with a defined node.fy has node.y reset to this value and node.vy set to zero. To unfix a node that was previously fixed, set node.fx and node.fy to null, or delete these properties.
简单地说就是,如果node的fx,fy值如果设置了,那么x,y就会设为fx,fy,而vx,vy相应设为0,表示节点静止。而如果再次将fx,fy设置为null,或删除这一属性,那么x,x, vx,vy又会再一次受力的作用确定其位置了。