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机制才是关键。

           

猜你喜欢

转载自blog.csdn.net/qq_44884577/article/details/89327967