D3 force 力导向图 研究之一 完美融合拖拽与缩放
本文采用的d3版本为第四版,4.9.1
- 1
先看实例效果,见图1, 在对节点进行缩放后,依旧能够做到以下两点:
1. 拖拽依旧能够完美做到鼠标跟随与连接关系跟随;
2. 缩放拖拽后,节点的位置依旧正确,利于数据保存;
再看操作失败的例子,见图2。
对现象进行分析,我们可以发现:
1. 鼠标跟随无差异,拖拽操作正常;
2. 节点位置正常;
3. 连线的更新状态错误;
继续诊断,我们可以得出这样的结论:连线的端点数据更新错误。 于是很显然,我们需要对tick事件进行修改,核心代码如下:
// 更新连线的端点数据links.attr('x1', d => { // 首先判断节点数据是否进行了缩放操作 if(d.source.scale !== undefined) { // 计算节点的真实位置 let scale = d.source.scale || 1, tx = d.source.tx || 0, x = d.source.x, rx = x * scale + tx return rx } return d.source.x})// 其他更新y1、x2、y2的代码略
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
在上面的代码中,我们需要知道节点是否进行缩放,理所当然我们需要注册自定义的缩放事件,核心代码如下:
/** * data: 当前结点绑定的数据 * index:当前结点的索引顺序 * els:缩放操作绑定元素的集合 */function zoomHandler(data, index, els){ // 指向当前结点 var transform = d3.zoomTransform(this), scale = transform.k, tx = transform.x, ty = transform.y // 将缩放参数写入节点绑定的数据 data.scale = scale data.tx = tx data.ty = ty // 执行缩放操作 // 偏移量在前,缩放在后,千万注意transform操作的先后顺序 d3.select(this).attr("transform", transform)}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
结论
理解力导向图、拖拽、缩放的核心事件是基础,熟练掌握SVG的transform机制才是关键。
本文采用的d3版本为第四版,4.9.1
- 1
先看实例效果,见图1, 在对节点进行缩放后,依旧能够做到以下两点:
1. 拖拽依旧能够完美做到鼠标跟随与连接关系跟随;
2. 缩放拖拽后,节点的位置依旧正确,利于数据保存;
再看操作失败的例子,见图2。
对现象进行分析,我们可以发现:
1. 鼠标跟随无差异,拖拽操作正常;
2. 节点位置正常;
3. 连线的更新状态错误;
继续诊断,我们可以得出这样的结论:连线的端点数据更新错误。 于是很显然,我们需要对tick事件进行修改,核心代码如下:
// 更新连线的端点数据links.attr('x1', d => { // 首先判断节点数据是否进行了缩放操作 if(d.source.scale !== undefined) { // 计算节点的真实位置 let scale = d.source.scale || 1, tx = d.source.tx || 0, x = d.source.x, rx = x * scale + tx return rx } return d.source.x})// 其他更新y1、x2、y2的代码略
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
在上面的代码中,我们需要知道节点是否进行缩放,理所当然我们需要注册自定义的缩放事件,核心代码如下:
/** * data: 当前结点绑定的数据 * index:当前结点的索引顺序 * els:缩放操作绑定元素的集合 */function zoomHandler(data, index, els){ // 指向当前结点 var transform = d3.zoomTransform(this), scale = transform.k, tx = transform.x, ty = transform.y // 将缩放参数写入节点绑定的数据 data.scale = scale data.tx = tx data.ty = ty // 执行缩放操作 // 偏移量在前,缩放在后,千万注意transform操作的先后顺序 d3.select(this).attr("transform", transform)}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
结论
理解力导向图、拖拽、缩放的核心事件是基础,熟练掌握SVG的transform机制才是关键。