vis.js is a dynamic, browser-based visualization library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
5.8 KiB

  1. /**
  2. * Created by Alex on 3/4/2015.
  3. */
  4. var util = require("../../util");
  5. var DataSet = require('../../DataSet');
  6. var DataView = require('../../DataView');
  7. var Edge = require("./components/edges/EdgeMain");
  8. class EdgesHandler {
  9. constructor(body, images, groups) {
  10. this.body = body;
  11. this.images = images;
  12. this.groups = groups;
  13. this.edgesListeners = {
  14. 'add': (event, params) => {this.add(params.items);},
  15. 'update': (event, params) => {this.update(params.items);},
  16. 'remove': (event, params) => {this.remove(params.items);}
  17. };
  18. var customScalingFunction = function (min,max,total,value) {
  19. if (max == min) {
  20. return 0.5;
  21. }
  22. else {
  23. var scale = 1 / (max - min);
  24. return Math.max(0,(value - min)*scale);
  25. }
  26. };
  27. this.options = {};
  28. this.defaultOptions = {
  29. customScalingFunction: customScalingFunction,
  30. widthMin: 1, //
  31. widthMax: 15,//
  32. width: 1,
  33. widthSelectionMultiplier: 2,
  34. hoverWidth: 1.5,
  35. value:1,
  36. style: 'line',
  37. color: {
  38. color:'#848484',
  39. highlight:'#848484',
  40. hover: '#848484'
  41. },
  42. opacity:1.0,
  43. fontColor: '#343434',
  44. fontSize: 14, // px
  45. fontFace: 'arial',
  46. fontFill: 'white',
  47. fontStrokeWidth: 0, // px
  48. fontStrokeColor: 'white',
  49. labelAlignment:'horizontal',
  50. arrowScaleFactor: 1,
  51. dash: {
  52. length: 10,
  53. gap: 5,
  54. altLength: undefined
  55. },
  56. inheritColor: "from", // to, from, false, true (== from)
  57. useGradients: false, // release in 4.0
  58. smoothEdges: {
  59. enabled: true,
  60. dynamic: true,
  61. type: "continuous",
  62. roundness: 0.5
  63. }
  64. };
  65. util.extend(this.options, this.defaultOptions);
  66. }
  67. setOptions(options) {
  68. }
  69. /**
  70. * Load edges by reading the data table
  71. * @param {Array | DataSet | DataView} edges The data containing the edges.
  72. * @private
  73. * @private
  74. */
  75. setData(edges) {
  76. var oldEdgesData = this.body.data.edges;
  77. if (edges instanceof DataSet || edges instanceof DataView) {
  78. this.body.data.edges = edges;
  79. }
  80. else if (Array.isArray(edges)) {
  81. this.body.data.edges = new DataSet();
  82. this.body.data.edges.add(edges);
  83. }
  84. else if (!edges) {
  85. this.body.data.edges = new DataSet();
  86. }
  87. else {
  88. throw new TypeError('Array or DataSet expected');
  89. }
  90. // TODO: is this null or undefined or false?
  91. if (oldEdgesData) {
  92. // unsubscribe from old dataset
  93. util.forEach(this.edgesListeners, (callback, event) => {oldEdgesData.off(event, callback);});
  94. }
  95. // remove drawn edges
  96. this.body.edges = {};
  97. // TODO: is this null or undefined or false?
  98. if (this.body.data.edges) {
  99. // subscribe to new dataset
  100. util.forEach(this.edgesListeners, (callback, event) => {this.body.data.edges.on(event, callback);});
  101. // draw all new nodes
  102. var ids = this.body.data.edges.getIds();
  103. this.add(ids);
  104. }
  105. this.body.emitter.emit("_dataChanged");
  106. }
  107. /**
  108. * Add edges
  109. * @param {Number[] | String[]} ids
  110. * @private
  111. */
  112. add(ids) {
  113. var edges = this.body.edges,
  114. edgesData = this.body.data.edges;
  115. for (var i = 0; i < ids.length; i++) {
  116. var id = ids[i];
  117. var oldEdge = edges[id];
  118. if (oldEdge) {
  119. oldEdge.disconnect();
  120. }
  121. var data = edgesData.get(id, {"showInternalIds" : true});
  122. edges[id] = new Edge(data, this.body, this.options);
  123. }
  124. this.body.emitter.emit("_dataChanged");
  125. }
  126. /**
  127. * Update existing edges, or create them when not yet existing
  128. * @param {Number[] | String[]} ids
  129. * @private
  130. */
  131. update(ids) {
  132. var edges = this.body.edges;
  133. var edgesData = this.body.data.edges;
  134. for (var i = 0; i < ids.length; i++) {
  135. var id = ids[i];
  136. var data = edgesData.get(id);
  137. var edge = edges[id];
  138. if (edge) {
  139. // update edge
  140. edge.disconnect();
  141. edge.setProperties(data);
  142. edge.connect();
  143. }
  144. else {
  145. // create edge
  146. edge = new Edge(data, this.body, this.options);
  147. this.body.edges[id] = edge;
  148. }
  149. }
  150. this.body.emitter.emit("_dataUpdated")
  151. }
  152. /**
  153. * Remove existing edges. Non existing ids will be ignored
  154. * @param {Number[] | String[]} ids
  155. * @private
  156. */
  157. remove(ids) {
  158. var edges = this.body.edges;
  159. for (var i = 0; i < ids.length; i++) {
  160. var id = ids[i];
  161. var edge = edges[id];
  162. if (edge !== undefined) {
  163. if (edge.via != null) {
  164. delete this.body.supportNodes[edge.via.id];
  165. }
  166. edge.disconnect();
  167. delete edges[id];
  168. }
  169. }
  170. this.body.emitter.emit("_dataChanged");
  171. }
  172. /**
  173. * Bezier curves require an anchor point to calculate the smooth flow. These points are nodes. These nodes are invisible but
  174. * are used for the force calculation.
  175. *
  176. * @private
  177. */
  178. createBezierNodes(specificEdges = this.body.edges) {
  179. var changedData = false;
  180. if (this.options.smoothEdges.enabled == true && this.options.smoothEdges.dynamic == true) {
  181. for (var edgeId in specificEdges) {
  182. if (specificEdges.hasOwnProperty(edgeId)) {
  183. var edge = specificEdges[edgeId];
  184. if (edge.via == null) {
  185. changedData = true;
  186. // TODO: move to nodes
  187. var nodeId = "edgeId:".concat(edge.id);
  188. var node = new Node(
  189. {id:nodeId,
  190. mass:1,
  191. shape:'circle',
  192. image:"",
  193. internalMultiplier:1
  194. },{},{},this.constants);
  195. this.body.supportNodes[nodeId] = node;
  196. edge.via = node;
  197. edge.via.parentEdgeId = edge.id;
  198. edge.positionBezierNode();
  199. }
  200. }
  201. }
  202. }
  203. if (changedData === true) {
  204. this.body.emitter.emit("_dataChanged");
  205. }
  206. }
  207. }
  208. export default EdgesHandler;