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.

133 lines
3.8 KiB

  1. import BezierEdgeBase from './util/BezierEdgeBase'
  2. class BezierEdgeDynamic extends BezierEdgeBase {
  3. constructor(options, body, labelModule) {
  4. //this.via = undefined; // Here for completeness but not allowed to defined before super() is invoked.
  5. super(options, body, labelModule); // --> this calls the setOptions below
  6. this._boundFunction = () => {this.positionBezierNode();};
  7. this.body.emitter.on("_repositionBezierNodes", this._boundFunction);
  8. }
  9. setOptions(options) {
  10. this.options = options;
  11. this.id = this.options.id;
  12. this.setupSupportNode();
  13. // when we change the physics state of the edge, we reposition the support node.
  14. if (this.options.physics !== options.physics) {
  15. this.via.setOptions({physics: this.options.physics})
  16. this.positionBezierNode();
  17. }
  18. this.connect();
  19. }
  20. connect() {
  21. this.from = this.body.nodes[this.options.from];
  22. this.to = this.body.nodes[this.options.to];
  23. if (this.from === undefined || this.to === undefined || this.options.physics === false) {
  24. this.via.setOptions({physics:false})
  25. }
  26. else {
  27. // fix weird behaviour where a selfreferencing node has physics enabled
  28. if (this.from.id === this.to.id) {
  29. this.via.setOptions({physics: false})
  30. }
  31. else {
  32. this.via.setOptions({physics: true})
  33. }
  34. }
  35. }
  36. /**
  37. * remove the support nodes
  38. * @returns {boolean}
  39. */
  40. cleanup() {
  41. this.body.emitter.off("_repositionBezierNodes", this._boundFunction);
  42. if (this.via !== undefined) {
  43. delete this.body.nodes[this.via.id];
  44. this.via = undefined;
  45. return true;
  46. }
  47. return false;
  48. }
  49. /**
  50. * Bezier curves require an anchor point to calculate the smooth flow. These points are nodes. These nodes are invisible but
  51. * are used for the force calculation.
  52. *
  53. * The changed data is not called, if needed, it is returned by the main edge constructor.
  54. * @private
  55. */
  56. setupSupportNode() {
  57. if (this.via === undefined) {
  58. var nodeId = "edgeId:" + this.id;
  59. var node = this.body.functions.createNode({
  60. id: nodeId,
  61. shape: 'circle',
  62. physics:true,
  63. hidden:true
  64. });
  65. this.body.nodes[nodeId] = node;
  66. this.via = node;
  67. this.via.parentEdgeId = this.id;
  68. this.positionBezierNode();
  69. }
  70. }
  71. positionBezierNode() {
  72. if (this.via !== undefined && this.from !== undefined && this.to !== undefined) {
  73. this.via.x = 0.5 * (this.from.x + this.to.x);
  74. this.via.y = 0.5 * (this.from.y + this.to.y);
  75. }
  76. else if (this.via !== undefined) {
  77. this.via.x = 0;
  78. this.via.y = 0;
  79. }
  80. }
  81. /**
  82. * Draw a line between two nodes
  83. * @param {CanvasRenderingContext2D} ctx
  84. * @private
  85. */
  86. _line(ctx) {
  87. // draw a straight line
  88. ctx.beginPath();
  89. ctx.moveTo(this.from.x, this.from.y);
  90. ctx.quadraticCurveTo(this.via.x, this.via.y, this.to.x, this.to.y);
  91. // draw shadow if enabled
  92. this.enableShadow(ctx);
  93. ctx.stroke();
  94. this.disableShadow(ctx);
  95. return this.via;
  96. }
  97. /**
  98. * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way
  99. * @param percentage
  100. * @param via
  101. * @returns {{x: number, y: number}}
  102. * @private
  103. */
  104. getPoint(percentage) {
  105. let t = percentage;
  106. let x = Math.pow(1 - t, 2) * this.from.x + (2 * t * (1 - t)) * this.via.x + Math.pow(t, 2) * this.to.x;
  107. let y = Math.pow(1 - t, 2) * this.from.y + (2 * t * (1 - t)) * this.via.y + Math.pow(t, 2) * this.to.y;
  108. return {x: x, y: y};
  109. }
  110. _findBorderPosition(nearNode, ctx) {
  111. return this._findBorderPositionBezier(nearNode, ctx, this.via);
  112. }
  113. _getDistanceToEdge(x1, y1, x2, y2, x3, y3) { // x3,y3 is the point
  114. return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, this.via);
  115. }
  116. }
  117. export default BezierEdgeDynamic;