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.

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