在 vis.js 中用最少的物理避免重叠边缘

Avoiding overlapping edges with minimal physics in vis.js

我正在使用 vis.js 构建故事可视化工具,其中一个关键功能是允许作者通过拖动手动定位节点。通常还有几条边具有相同的起点和终点节点。没有物理学,这些边缘会重叠。

目前,为了避免边缘重叠,每当创建新边缘以排斥彼此重叠的边缘时,我都会在一小段时间内启用物理。理想情况下,我会始终禁用物理并且边缘不会重叠,但我认为这是不可能的。

是否有关于如何应用可见物理的任何建议,以便在节点拖动时禁用它,快速稳定并防止边缘重叠?

如果有人遇到这个问题,解决方案是根据有多少条边具有相同的起点和终点节点来计算每条边的圆度。

示例:http://jsbin.com/wojanuboxi/edit?html,js,output

 var nodes = new vis.DataSet([
 {id: 1, label: '1'},
 {id: 2, label: '2'},
 {id: 3, label: '3'}
]);
var edges = new vis.DataSet([
  {id: 1, from: 1, to: 2, smooth: {type: 'curvedCW', roundness: 0.2}},
  {id: 2, from: 1, to: 2, smooth: {type: 'curvedCW', roundness: -2.2}},
  {id: 5, from: 1, to: 2, label: 5,  smooth: {type: 'curvedCW', roundness: 0.4}},
  {id: 6, from: 1, to: 2, label: 6, smooth: {type: 'curvedCW', roundness: -2.4}},

  {id: 3, from: 1, to: 3, smooth: {type: 'curvedCW', roundness: -2.1}},
  {id: 4, from: 1, to: 3, smooth: {type: 'curvedCW', roundness: 0.1}}
]);
var data = {
  nodes: nodes,
  edges: edges
};
var options = {
  physics: false,
  layout: {
    hierarchical: {
      direction: 'UD'
    }
  }
};

var networkContainer = document.getElementById('networkContainer');
var network = new vis.Network(networkContainer, data, options);

禁用物理变量后,我找不到有用的重叠问题解决方案。对于边缘。我已经为 this.this 创建了一个临时解决方案可以解决少量边缘的重叠问题。但是对于太多的边,会再次出现重叠问题。圆度值设置边缘的圆度。如果我们给它一个负值和正值范围内的随机值,我们可能会倒霉。 :)

getConnectedEdgesCountAndCreateRandomRoundness(toRouterId: number, fromRouterId: number): number {
            var randomRoundness: number = 0;
            var connectedEdgesCount = this.network.getConnectedEdges(toRouterId).filter(value => this.network.getConnectedEdges(fromRouterId).includes(value)).length;
            if(connectedEdgesCount === 0){
                randomRoundness = 0;
            } 
            else if (connectedEdgesCount === 1){
                randomRoundness = this.generateRandomNumber(-0.25,0.25);
            }
            else if (connectedEdgesCount === 2){
                randomRoundness = this.generateRandomNumber(-0.5,0.5);
            }
            else {
                randomRoundness = this.generateRandomNumber(-1.25,1.25);
            }

            return randomRoundness;
        }
      
                    var randomRoundness = this.getConnectedEdgesCountAndCreateRandomRoundness(this.toRouterId,this.fromRouterId);

                    this.edges.add({
                        id: this.circuitEdge.id,
                        from: this.fromRouterNode.id,
                        to: this.toRouterNode.id,
                        label: this.circuitEdge.name,
                        type: this.circuitEdge.type,
                        color: visEdgeColor,
                        smooth: { enabled: true, type: "curvedCW", roundness: randomRoundness}
                    });