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.

212 lines
5.6 KiB

  1. /**
  2. * The Base class for all Nodes.
  3. *
  4. * @param {Object} options
  5. * @param {Object} body
  6. * @param {Label} labelModule
  7. * @constructor NodeBase
  8. */
  9. class NodeBase {
  10. constructor(options, body, labelModule) {
  11. this.body = body;
  12. this.labelModule = labelModule;
  13. this.setOptions(options);
  14. this.top = undefined;
  15. this.left = undefined;
  16. this.height = undefined;
  17. this.width = undefined;
  18. this.radius = undefined;
  19. this.margin = undefined;
  20. this.refreshNeeded = true;
  21. this.boundingBox = {top: 0, left: 0, right: 0, bottom: 0};
  22. }
  23. setOptions(options) {
  24. this.options = options;
  25. }
  26. _setMargins(labelModule) {
  27. this.margin = {};
  28. if (this.options.margin) {
  29. if (typeof this.options.margin == 'object') {
  30. this.margin.top = this.options.margin.top;
  31. this.margin.right = this.options.margin.right;
  32. this.margin.bottom = this.options.margin.bottom;
  33. this.margin.left = this.options.margin.left;
  34. } else {
  35. this.margin.top = this.options.margin;
  36. this.margin.right = this.options.margin;
  37. this.margin.bottom = this.options.margin;
  38. this.margin.left = this.options.margin;
  39. }
  40. }
  41. labelModule.adjustSizes(this.margin)
  42. }
  43. _distanceToBorder(ctx,angle) {
  44. var borderWidth = this.options.borderWidth;
  45. this.resize(ctx);
  46. return Math.min(
  47. Math.abs(this.width / 2 / Math.cos(angle)),
  48. Math.abs(this.height / 2 / Math.sin(angle))) + borderWidth;
  49. }
  50. enableShadow(ctx, values) {
  51. if (values.shadow) {
  52. ctx.shadowColor = values.shadowColor;
  53. ctx.shadowBlur = values.shadowSize;
  54. ctx.shadowOffsetX = values.shadowX;
  55. ctx.shadowOffsetY = values.shadowY;
  56. }
  57. }
  58. disableShadow(ctx, values) {
  59. if (values.shadow) {
  60. ctx.shadowColor = 'rgba(0,0,0,0)';
  61. ctx.shadowBlur = 0;
  62. ctx.shadowOffsetX = 0;
  63. ctx.shadowOffsetY = 0;
  64. }
  65. }
  66. enableBorderDashes(ctx, values) {
  67. if (values.borderDashes !== false) {
  68. if (ctx.setLineDash !== undefined) {
  69. let dashes = values.borderDashes;
  70. if (dashes === true) {
  71. dashes = [5,15]
  72. }
  73. ctx.setLineDash(dashes);
  74. }
  75. else {
  76. console.warn("setLineDash is not supported in this browser. The dashed borders cannot be used.");
  77. this.options.shapeProperties.borderDashes = false;
  78. values.borderDashes = false;
  79. }
  80. }
  81. }
  82. disableBorderDashes(ctx, values) {
  83. if (values.borderDashes !== false) {
  84. if (ctx.setLineDash !== undefined) {
  85. ctx.setLineDash([0]);
  86. }
  87. else {
  88. console.warn("setLineDash is not supported in this browser. The dashed borders cannot be used.");
  89. this.options.shapeProperties.borderDashes = false;
  90. values.borderDashes = false;
  91. }
  92. }
  93. }
  94. /**
  95. * Determine if the shape of a node needs to be recalculated.
  96. *
  97. * @param {boolean} selected
  98. * @param {boolean} hover
  99. * @returns {boolean}
  100. * @protected
  101. */
  102. needsRefresh(selected, hover) {
  103. if (this.refreshNeeded === true) {
  104. // This is probably not the best location to reset this member.
  105. // However, in the current logic, it is the most convenient one.
  106. this.refreshNeeded = false;
  107. return true;
  108. }
  109. return (this.width === undefined) || (this.labelModule.differentState(selected, hover));
  110. }
  111. initContextForDraw(ctx, values) {
  112. var borderWidth = values.borderWidth / this.body.view.scale;
  113. ctx.lineWidth = Math.min(this.width, borderWidth);
  114. ctx.strokeStyle = values.borderColor;
  115. ctx.fillStyle = values.color;
  116. }
  117. performStroke(ctx, values) {
  118. var borderWidth = values.borderWidth / this.body.view.scale;
  119. //draw dashed border if enabled, save and restore is required for firefox not to crash on unix.
  120. ctx.save();
  121. // if borders are zero width, they will be drawn with width 1 by default. This prevents that
  122. if (borderWidth > 0) {
  123. this.enableBorderDashes(ctx, values);
  124. //draw the border
  125. ctx.stroke();
  126. //disable dashed border for other elements
  127. this.disableBorderDashes(ctx, values);
  128. }
  129. ctx.restore();
  130. }
  131. performFill(ctx, values) {
  132. // draw shadow if enabled
  133. this.enableShadow(ctx, values);
  134. // draw the background
  135. ctx.fill();
  136. // disable shadows for other elements.
  137. this.disableShadow(ctx, values);
  138. this.performStroke(ctx, values);
  139. }
  140. _addBoundingBoxMargin(margin) {
  141. this.boundingBox.left -= margin;
  142. this.boundingBox.top -= margin;
  143. this.boundingBox.bottom += margin;
  144. this.boundingBox.right += margin;
  145. }
  146. /**
  147. * Actual implementation of this method call.
  148. *
  149. * Doing it like this makes it easier to override
  150. * in the child classes.
  151. *
  152. * @param {number} x width
  153. * @param {number} y height
  154. * @param {CanvasRenderingContext2D} ctx
  155. * @param {boolean} selected
  156. * @param {boolean} hover
  157. * @private
  158. */
  159. _updateBoundingBox(x, y, ctx, selected, hover) {
  160. if (ctx !== undefined) {
  161. this.resize(ctx, selected, hover);
  162. }
  163. this.left = x - this.width / 2;
  164. this.top = y - this.height/ 2;
  165. this.boundingBox.left = this.left;
  166. this.boundingBox.top = this.top;
  167. this.boundingBox.bottom = this.top + this.height;
  168. this.boundingBox.right = this.left + this.width;
  169. }
  170. /**
  171. * Default implementation of this method call.
  172. * This acts as a stub which can be overridden.
  173. *
  174. * @param {number} x width
  175. * @param {number} y height
  176. * @param {CanvasRenderingContext2D} ctx
  177. * @param {boolean} selected
  178. * @param {boolean} hover
  179. */
  180. updateBoundingBox(x, y, ctx, selected, hover) {
  181. this._updateBoundingBox(x, y, ctx, selected, hover);
  182. }
  183. }
  184. export default NodeBase;