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.

229 lines
5.4 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 Node = require("./components/nodes/NodeMain");
  8. class NodesHandler {
  9. constructor(body, images, groups, layoutEngine) {
  10. this.body = body;
  11. this.images = images;
  12. this.groups = groups;
  13. this.layoutEngine = layoutEngine;
  14. // create the node API in the body container
  15. this.body.functions.createNode = this.create.bind(this);
  16. this.nodesListeners = {
  17. 'add': (event, params) => {this.add(params.items);},
  18. 'update': (event, params) => {this.update(params.items, params.data);},
  19. 'remove': (event, params) => {this.remove(params.items);}
  20. };
  21. this.options = {};
  22. this.defaultOptions = {
  23. mass: 1,
  24. //radiusMin: 10,
  25. //radiusMax: 30,
  26. radius: 10,
  27. scaling: {
  28. min: 10,
  29. max: 40,
  30. label: {
  31. enabled: true,
  32. min: 14,
  33. max: 30,
  34. maxVisible: 30,
  35. drawThreshold: 3
  36. },
  37. customScalingFunction: function (min,max,total,value) {
  38. if (max == min) {
  39. return 0.5;
  40. }
  41. else {
  42. var scale = 1 / (max - min);
  43. return Math.max(0,(value - min)*scale);
  44. }
  45. }
  46. },
  47. shape: 'ellipse',
  48. image: undefined, // --> URL
  49. //widthMin: 16, // px
  50. //widthMax: 64, // px
  51. label: undefined,
  52. labelStyle: {
  53. fontColor: 'black',
  54. fontSize: 14, // px
  55. fontFace: 'verdana',
  56. fontFill: undefined,
  57. fontStrokeWidth: 0, // px
  58. fontStrokeColor: '#ffffff',
  59. //scaleFontWithValue: false,
  60. //fontSizeMin: 14,
  61. //fontSizeMax: 30,
  62. //fontSizeMaxVisible: 30,
  63. //fontDrawThreshold: 3
  64. },
  65. value: 1,
  66. color: {
  67. border: '#2B7CE9',
  68. background: '#97C2FC',
  69. highlight: {
  70. border: '#2B7CE9',
  71. background: '#D2E5FF'
  72. },
  73. hover: {
  74. border: '#2B7CE9',
  75. background: '#D2E5FF'
  76. }
  77. },
  78. group: undefined,
  79. borderWidth: 1,
  80. borderWidthSelected: undefined,
  81. physics: true,
  82. hidden: false,
  83. icon: {
  84. iconFontFace: undefined, //'FontAwesome',
  85. code: undefined, //'\uf007',
  86. iconSize: undefined, //50,
  87. iconColor: undefined //'#aa00ff'
  88. }
  89. };
  90. util.extend(this.options, this.defaultOptions);
  91. }
  92. setOptions(options) {
  93. }
  94. /**
  95. * Set a data set with nodes for the network
  96. * @param {Array | DataSet | DataView} nodes The data containing the nodes.
  97. * @private
  98. */
  99. setData(nodes) {
  100. var oldNodesData = this.body.data.nodes;
  101. if (nodes instanceof DataSet || nodes instanceof DataView) {
  102. this.body.data.nodes = nodes;
  103. }
  104. else if (Array.isArray(nodes)) {
  105. this.body.data.nodes = new DataSet();
  106. this.body.data.nodes.add(nodes);
  107. }
  108. else if (!nodes) {
  109. this.body.data.nodes = new DataSet();
  110. }
  111. else {
  112. throw new TypeError('Array or DataSet expected');
  113. }
  114. if (oldNodesData) {
  115. // unsubscribe from old dataset
  116. util.forEach(this.nodesListeners, function (callback, event) {
  117. oldNodesData.off(event, callback);
  118. });
  119. }
  120. // remove drawn nodes
  121. this.body.nodes = {};
  122. if (this.body.data.nodes) {
  123. // subscribe to new dataset
  124. var me = this;
  125. util.forEach(this.nodesListeners, function (callback, event) {
  126. me.body.data.nodes.on(event, callback);
  127. });
  128. // draw all new nodes
  129. var ids = this.body.data.nodes.getIds();
  130. this.add(ids);
  131. }
  132. this.body.emitter.emit("_dataChanged");
  133. }
  134. /**
  135. * Add nodes
  136. * @param {Number[] | String[]} ids
  137. * @private
  138. */
  139. add(ids) {
  140. var id;
  141. var newNodes = [];
  142. for (var i = 0; i < ids.length; i++) {
  143. id = ids[i];
  144. var data = this.body.data.nodes.get(id);
  145. var node = new Node(data, this.images, this.groups, this.options);
  146. newNodes.push(node);
  147. this.body.nodes[id] = node; // note: this may replace an existing node
  148. }
  149. this.layoutEngine.positionInitially(newNodes);
  150. this.body.emitter.emit("_dataChanged");
  151. }
  152. /**
  153. * Update existing nodes, or create them when not yet existing
  154. * @param {Number[] | String[]} ids
  155. * @private
  156. */
  157. update(ids, changedData) {
  158. var nodes = this.body.nodes;
  159. var dataChanged = false;
  160. for (var i = 0; i < ids.length; i++) {
  161. var id = ids[i];
  162. var node = nodes[id];
  163. var data = changedData[i];
  164. if (node !== undefined) {
  165. // update node
  166. node.setOptions(data, this.constants);
  167. }
  168. else {
  169. dataChanged = true;
  170. // create node
  171. node = new Node(properties, this.images, this.groups, this.constants);
  172. nodes[id] = node;
  173. }
  174. }
  175. if (dataChanged === true) {
  176. this.body.emitter.emit("_dataChanged");
  177. }
  178. else {
  179. this.body.emitter.emit("_dataUpdated");
  180. }
  181. }
  182. /**
  183. * Remove existing nodes. If nodes do not exist, the method will just ignore it.
  184. * @param {Number[] | String[]} ids
  185. * @private
  186. */
  187. remove(ids) {
  188. var nodes = this.body.nodes;
  189. for (let i = 0; i < ids.length; i++) {
  190. var id = ids[i];
  191. delete nodes[id];
  192. }
  193. this.body.emitter.emit("_dataChanged");
  194. }
  195. create(properties) {
  196. return new Node(properties, this.images, this.groups, this.options)
  197. }
  198. }
  199. export default NodesHandler;