当前位置:   article > 正文

JSPlumb.js 绘制关系拓扑图(力导向布局算法简单实现)

jsplumb.js

JSPlumb.js 绘制关系拓扑图(力导向布局算法简单实现)

d3 echarts 都可以画关系拓扑图(有环),但是总觉得不是自己想要的,改起来也很麻烦,所以可以用JSPlumb 自己绘制自己的关系拓扑图,拓扑图 = 绘图 + 自动布局算法。jsplumb 可以实现绘自己的结点,而自动布局则可以采用 力导向布局算法。
这里参考的是 https://www.jianshu.com/p/d3c64a39535a

随机生成结点 与结点的位置

	/**
 * A force directed graph layout implementation by liuchang on 2018/05/10.
 */
	const CANVAS_WIDTH = 1000;
	const CANVAS_HEIGHT = 1000;
	let k;
	let mNodeList = [];
	let mEdgeList = [];
	let mDxMap = {
   };
	let mDyMap = {
   };
	let mNodeMap = {
   };
	var json ={
   } ;

function ForceDirected() {
   
  //generate nodes and edges
  for (let i = 0; i < 20; i++) {
   
    mNodeList.push(new Node(i));
  }

  for (let i = 0; i < 20; i++) {
   
    let edgeCount = Math.random() * 8 + 1;
    for (let j = 0; j < edgeCount; j++) {
   
      let targetId = Math.floor(Math.random() * 20);
      let edge = new Edge(i, targetId);
      mEdgeList.push(edge);
    }
  }
  if (mNodeList && mEdgeList) {
   
    k = Math.sqrt(CANVAS_WIDTH * CANVAS_HEIGHT / mNodeList.length);
  }
  for (let i = 0; i < mNodeList.length; i++) {
   
    let node = mNodeList[i];
    if (node) {
   
      mNodeMap[node.id] = node;
    }
  }

  //随机生成坐标. Generate coordinates randomly.
  let initialX, initialY, initialSize = 40.0;
  for (let i in mNodeList) {
   
    initialX = CANVAS_WIDTH * .5;
    initialY = CANVAS_HEIGHT * .5;
    mNodeList[i].x = initialX + initialSize * (Math.random() - .5);
    mNodeList[i].y = initialY + initialSize * (Math.random() - .5);
  }

  //迭代200次. Iterate 200 times.
  for (let i = 0; i < 200; i++) {
   
    calculateRepulsive();
    calculateTraction();
    updateCoordinates();
  }
  
  json = JSON.stringify(new Result(mNodeList, mEdgeList));
  //console.log();
  
}

function Node(id = null) {
   
  this.id = id;
  this.x = 22;
  this.y = null;
}
function Edge(source = null, target = null) {
   
  this.source = source;
  this.target = target;
}

/**
 * 计算两个Node的斥力产生的单位位移。
 * Calculate the displacement generated by the repulsive force between two nodes.*
 */
function calculateRepulsive() {
   
  let ejectFactor = 6;
  let distX, distY, dist;
  for (let i = 0; i < mNodeList.length; i++) {
   
    mDxMap[mNodeList[i].id] = 0.0;
    mDyMap[mNodeList[i].id] = 0.0;
    for (let j = 0; j < mNodeList.length; j++) {
   
      if (i !== j) {
   
        distX = mNodeList[i].x - mNodeList[j].x;
        distY = mNodeList[i].y - mNodeList[j].y;
        dist = Math.sqrt(distX * distX + distY * distY);
      }
      if (dist < 30) {
   
        ejectFactor = 5;
      }
      if (dist > 0 && dist < 250) {
   
        let id = mNodeList[i].id;
        mDxMap[id] = mDxMap[id] + distX / dist * k * k / dist * ejectFactor;
        mDyMap[id] = mDyMap[id] + distY / dist * k * k / dist * ejectFactor;
      }
    }
  }
}

/**
 * 计算Edge的引力对两端Node产生的引力。
 * Calculate the traction force generated by the edge acted on the two nodes of its two ends.
 */
function calculateTraction() {
   
  let condenseFactor = 3;
  let startNode, endNode;
  for (let e = 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/117153
推荐阅读
相关标签
  

闽ICP备14008679号