js实现流图自动布局算法实现?

目前真正的问题:需要一个通用的连线路径画法 drawLinePath

let drawLinePath = (node1,node2,nodes) => {
  //通过node1和node2的节点大小和坐标信息绘制一条通用优雅的有向连线
  return linePath;
}

更:根据目前的算法和需求分析,引入力导布局算法或许是最优解。目前的做法是使用Webgraphviz,在需要自动布局时渲染出svg画板,再通过设置setTimeout(Viz渲染生成的dom在主线程中获取不到),在里边获取刚生成的dom节点的信息和坐标,把坐标信息赋给真正的流图画板。此时,通过Viz()生成的svg画板功成身退,毁尸灭迹。

结果,坐标信息拿到了,差个坐标的相对位置问题和连线路径。
发现拿到的坐标位置和真正画板中节点的坐标有误差(这个只能手动做点调整)。
主要缺的还是连线路径,没有统一的连线公式,准确说是不知道viz里的连线规则

这两天试着看了d3源码(因为没找到其他力导布局的js代码实现或简单易解的例子),现在还是一脸蒙蔽。


原问题描述:
目的:给出节点和连线的json数据,用vue绘制一个流图。画板中的流图为若干个有向图组成、要求流图中的画板可缩放,节点大小可设置坐标能获取、能填充图片、能在下方显示标签信息、且节点和连线都有事件监听,节点可移动连线位置随之更新,最最重要的是画板能自动布局

json数据格式如下:
{
    "nodes":{
      "node1":{
        "id": "node1",
        "imgSrc": "img1",
        "label": "节点1",
        "width": "50",
        "height": "50",
      },
      "node2":{
        "id": "node2",
        "imgSrc": "img2",
        "label": "节点2",
        "width": "50",
        "height": "50",
      },
      "node2":{
        "id": "node2",
        "imgSrc": "img1",
        "label": "节点2",
        "width": "50",
        "height": "50",
      }
    },
    "lines":[
      ["node1","node2"] //表示node1->node2
    ]
}

clipboard.png

上图为以前自己用vue+svg实现的,没用其他框架和库,以上要求实现了,就是自动布局算法自己写的有点糙。
现在想要把自动布局算法那块优化,自动布局和连线的路径画法是有关联的,不希望有连线重叠从而影响连线的判断。
网上查到有力导布局,觉得这个或许能实现我的目的。但是不知道怎么用,用了之后连线的路径又该怎么设置,希望老司机能指点一下

回答:

对于流图(有向无环图)布局,不建议用力引导布局,可以用bary-center算法,从左到右扫描,下一层的点的顺序由上一层父节点的平均值获得,得到顺序后再算具体坐标,再从右向左扫描,直到迭代到合适的线交叉率为止。
可以参考d3的桑吉图(d3-sankey)实现;也可以参考dagre.js(我都是直接调用的。。。)。

回答:

这个是一个很复杂的工程,建议参考D3实现代码中关于力导向图处理实现算法。
另外,我提供一个其它的思路:
先生成所有路径,按层级递归生成,每次生成1个枝干(深度优先),这样对1个枝干来说,每个节点位置都可以确定出来,这样就不会存在交叉的问题。因为所有后绘制的节点都是在已有基础上绘制,已有的节点是位置确定的,比如

root--node1--node1-1--node1-1-1
    |      |        |-node1-1-2
    |      |
    |      |-node1-2--node1-2-1
    |      |        |-node1-2-2
    |      |
    |      |-node1-3
    |
    |-node2
    
    ...         

暂无评论

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注