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.

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