【问题标题】:algorithm approach to render a node mesh in an overlap free way以无重叠方式渲染节点网格的算法方法
【发布时间】:2016-12-09 15:35:20
【问题描述】:

我有几个节点(例如应用程序名称)和几个带标签的边(例如信息流/系统接口及其信息对象)。我希望能够编写一个 javascript 脚本,以无重叠的方式绘制节点网格(例如信息流程图),这意味着:

  • 边的标签不被节点和/或彼此重叠
  • 节点不被边缘线和/或边缘标签和/或彼此重叠

还需要以尽可能多的边缘线可见且不会相互混淆的方式放置节点 - 因此需要进行某种优化。 还要求任何节点都可能连接到任何其他节点。

为了做到这一点,我正在寻找一个关于如何做到这一点的粗略想法(高级伪代码)或者一个现成的 javascript 实现。

我对以下内容不感兴趣,因为我知道它是如何工作的:

  • 放置/移动 div
  • 绘制 svg 线条
  • 必须进行任何类型的数据转换工作或数据资产培训(向量、矩阵、稀疏矩阵...)

我从以下开始:

  1. 把只有一条边的节点放到画布的外层空间
  2. 将连接到它们的节点放在靠近它们的地方

这样我就可以在画布上轻松地展开一棵树。最初的想法是从那里进行一些排序和分组。但是,我很难将子树从网格结构中分组,并且不知何故陷入了其中。

我还认为碰撞检测可能会对我有所帮助。但是,我没有明白这如何帮助我放置节点,以便边缘在可见性方面是最佳的。

为了让这一点在这里更加明显,输入数据结构的外观如下:

var nodeseq=[  // id,name
{id:'i1',name:'app1'},
{id:'i2',name:'app2'};
...
];

var edgeseq=[  // id,sourcenodeid,targetnodeid,label
{id:'i1',sourcenodeid:'i33',targetnodeid:'i25',label:'Invoice'},
{id:'i2',sourcenodeid:'i3',targetnodeid:'i5',label:'Advise'},
...
];

【问题讨论】:

    标签: javascript algorithm mesh


    【解决方案1】:

    或者一个现成的 javascript 实现

    Springy.js 可能适合您的需求...自从我上次使用它已经有一段时间了,但它有一个非常简单的 API,因此值得一试。一个例子:

    var nodeseq = [  // id,name
      {id:'i1',name:'app1'},
      {id:'i2',name:'app2'},
      {id:'i3',name:'app3'},
      {id:'i4',name:'app4'},
    ];
    
    var edgeseq = [  // id,sourcenodeid,targetnodeid,label
      {id:'i1',sourcenodeid:'i1',targetnodeid:'i2',label:'Invoice'},
      {id:'i2',sourcenodeid:'i1',targetnodeid:'i3',label:'Advise'},
      {id:'i3',sourcenodeid:'i3',targetnodeid:'i3',label:'Test'},
      {id:'i4',sourcenodeid:'i3',targetnodeid:'i4',label:'Test'},
      {id:'i5',sourcenodeid:'i2',targetnodeid:'i3',label:'Test'},
    ];
    
    var graph = new Springy.Graph();
    var createNode = node => graph.newNode({label: node.name });
    
    var nodeMap = makeMap("id", nodeseq, createNode);
    
    // connect them with an edge
    edgeseq.forEach(edge => graph.newEdge(
      nodeMap[edge.sourcenodeid],
      nodeMap[edge.targetnodeid],
      { label: edge.label }
    ));
    
    $('canvas').springy({ graph: graph });
    
    // Utils
    function makeMap(prop, arr, t) {
      t = t || (v => v);
      return arr
        .reduce((map, item) => Object.assign(map, { 
          [item[prop]] : t(item) 
          }), {}); 
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/springy/2.7.1/springyui.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/springy/2.7.1/springy.min.js"></script>
    <canvas width="400" height="200" />

    【讨论】:

    • 哇。是否也可以将标签放在边缘?
    • 当然,newEdge 方法采用第三个参数,允许您指定属性。我在答案中编辑了示例;我们现在传递label 属性来标记箭头。
    猜你喜欢
    • 2019-07-22
    • 1970-01-01
    • 2013-09-29
    • 1970-01-01
    • 2010-12-12
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    • 2021-06-01
    相关资源
    最近更新 更多