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.

240 lines
7.8 KiB

  1. import BezierEdgeBase from './util/BezierEdgeBase'
  2. class BezierEdgeStatic extends BezierEdgeBase {
  3. constructor(options, body, labelModule) {
  4. super(options, body, labelModule);
  5. }
  6. cleanup() {
  7. return false;
  8. }
  9. /**
  10. * Draw a line between two nodes
  11. * @param {CanvasRenderingContext2D} ctx
  12. * @private
  13. */
  14. _line(ctx) {
  15. // draw a straight line
  16. ctx.beginPath();
  17. ctx.moveTo(this.from.x, this.from.y);
  18. let via = this._getViaCoordinates();
  19. let returnValue = via;
  20. // fallback to normal straight edges
  21. if (via.x === undefined) {
  22. ctx.lineTo(this.to.x, this.to.y);
  23. returnValue = undefined;
  24. }
  25. else {
  26. ctx.quadraticCurveTo(via.x, via.y, this.to.x, this.to.y);
  27. }
  28. // draw shadow if enabled
  29. this.enableShadow(ctx);
  30. ctx.stroke();
  31. this.disableShadow(ctx);
  32. return returnValue;
  33. }
  34. _getViaCoordinates() {
  35. let xVia = undefined;
  36. let yVia = undefined;
  37. let factor = this.options.smooth.roundness;
  38. let type = this.options.smooth.type;
  39. let dx = Math.abs(this.from.x - this.to.x);
  40. let dy = Math.abs(this.from.y - this.to.y);
  41. if (type === 'discrete' || type === 'diagonalCross') {
  42. if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) {
  43. if (this.from.y > this.to.y) {
  44. if (this.from.x < this.to.x) {
  45. xVia = this.from.x + factor * dy;
  46. yVia = this.from.y - factor * dy;
  47. }
  48. else if (this.from.x > this.to.x) {
  49. xVia = this.from.x - factor * dy;
  50. yVia = this.from.y - factor * dy;
  51. }
  52. }
  53. else if (this.from.y < this.to.y) {
  54. if (this.from.x < this.to.x) {
  55. xVia = this.from.x + factor * dy;
  56. yVia = this.from.y + factor * dy;
  57. }
  58. else if (this.from.x > this.to.x) {
  59. xVia = this.from.x - factor * dy;
  60. yVia = this.from.y + factor * dy;
  61. }
  62. }
  63. if (type === "discrete") {
  64. xVia = dx < factor * dy ? this.from.x : xVia;
  65. }
  66. }
  67. else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) {
  68. if (this.from.y > this.to.y) {
  69. if (this.from.x < this.to.x) {
  70. xVia = this.from.x + factor * dx;
  71. yVia = this.from.y - factor * dx;
  72. }
  73. else if (this.from.x > this.to.x) {
  74. xVia = this.from.x - factor * dx;
  75. yVia = this.from.y - factor * dx;
  76. }
  77. }
  78. else if (this.from.y < this.to.y) {
  79. if (this.from.x < this.to.x) {
  80. xVia = this.from.x + factor * dx;
  81. yVia = this.from.y + factor * dx;
  82. }
  83. else if (this.from.x > this.to.x) {
  84. xVia = this.from.x - factor * dx;
  85. yVia = this.from.y + factor * dx;
  86. }
  87. }
  88. if (type === "discrete") {
  89. yVia = dy < factor * dx ? this.from.y : yVia;
  90. }
  91. }
  92. }
  93. else if (type === "straightCross") {
  94. if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) { // up - down
  95. xVia = this.from.x;
  96. if (this.from.y < this.to.y) {
  97. yVia = this.to.y - (1 - factor) * dy;
  98. }
  99. else {
  100. yVia = this.to.y + (1 - factor) * dy;
  101. }
  102. }
  103. else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) { // left - right
  104. if (this.from.x < this.to.x) {
  105. xVia = this.to.x - (1 - factor) * dx;
  106. }
  107. else {
  108. xVia = this.to.x + (1 - factor) * dx;
  109. }
  110. yVia = this.from.y;
  111. }
  112. }
  113. else if (type === 'horizontal') {
  114. if (this.from.x < this.to.x) {
  115. xVia = this.to.x - (1 - factor) * dx;
  116. }
  117. else {
  118. xVia = this.to.x + (1 - factor) * dx;
  119. }
  120. yVia = this.from.y;
  121. }
  122. else if (type === 'vertical') {
  123. xVia = this.from.x;
  124. if (this.from.y < this.to.y) {
  125. yVia = this.to.y - (1 - factor) * dy;
  126. }
  127. else {
  128. yVia = this.to.y + (1 - factor) * dy;
  129. }
  130. }
  131. else if (type === 'curvedCW') {
  132. dx = this.to.x - this.from.x;
  133. dy = this.from.y - this.to.y;
  134. let radius = Math.sqrt(dx * dx + dy * dy);
  135. let pi = Math.PI;
  136. let originalAngle = Math.atan2(dy, dx);
  137. let myAngle = (originalAngle + ((factor * 0.5) + 0.5) * pi) % (2 * pi);
  138. xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle);
  139. yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle);
  140. }
  141. else if (type === 'curvedCCW') {
  142. dx = this.to.x - this.from.x;
  143. dy = this.from.y - this.to.y;
  144. let radius = Math.sqrt(dx * dx + dy * dy);
  145. let pi = Math.PI;
  146. let originalAngle = Math.atan2(dy, dx);
  147. let myAngle = (originalAngle + ((-factor * 0.5) + 0.5) * pi) % (2 * pi);
  148. xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle);
  149. yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle);
  150. }
  151. else { // continuous
  152. if (Math.abs(this.from.x - this.to.x) < Math.abs(this.from.y - this.to.y)) {
  153. if (this.from.y > this.to.y) {
  154. if (this.from.x < this.to.x) {
  155. xVia = this.from.x + factor * dy;
  156. yVia = this.from.y - factor * dy;
  157. xVia = this.to.x < xVia ? this.to.x : xVia;
  158. }
  159. else if (this.from.x > this.to.x) {
  160. xVia = this.from.x - factor * dy;
  161. yVia = this.from.y - factor * dy;
  162. xVia = this.to.x > xVia ? this.to.x : xVia;
  163. }
  164. }
  165. else if (this.from.y < this.to.y) {
  166. if (this.from.x < this.to.x) {
  167. xVia = this.from.x + factor * dy;
  168. yVia = this.from.y + factor * dy;
  169. xVia = this.to.x < xVia ? this.to.x : xVia;
  170. }
  171. else if (this.from.x > this.to.x) {
  172. xVia = this.from.x - factor * dy;
  173. yVia = this.from.y + factor * dy;
  174. xVia = this.to.x > xVia ? this.to.x : xVia;
  175. }
  176. }
  177. }
  178. else if (Math.abs(this.from.x - this.to.x) > Math.abs(this.from.y - this.to.y)) {
  179. if (this.from.y > this.to.y) {
  180. if (this.from.x < this.to.x) {
  181. xVia = this.from.x + factor * dx;
  182. yVia = this.from.y - factor * dx;
  183. yVia = this.to.y > yVia ? this.to.y : yVia;
  184. }
  185. else if (this.from.x > this.to.x) {
  186. xVia = this.from.x - factor * dx;
  187. yVia = this.from.y - factor * dx;
  188. yVia = this.to.y > yVia ? this.to.y : yVia;
  189. }
  190. }
  191. else if (this.from.y < this.to.y) {
  192. if (this.from.x < this.to.x) {
  193. xVia = this.from.x + factor * dx;
  194. yVia = this.from.y + factor * dx;
  195. yVia = this.to.y < yVia ? this.to.y : yVia;
  196. }
  197. else if (this.from.x > this.to.x) {
  198. xVia = this.from.x - factor * dx;
  199. yVia = this.from.y + factor * dx;
  200. yVia = this.to.y < yVia ? this.to.y : yVia;
  201. }
  202. }
  203. }
  204. }
  205. return {x: xVia, y: yVia};
  206. }
  207. _findBorderPosition(nearNode, ctx, options = {}) {
  208. return this._findBorderPositionBezier(nearNode, ctx, options.via);
  209. }
  210. _getDistanceToEdge(x1, y1, x2, y2, x3, y3, via = this._getViaCoordinates()) { // x3,y3 is the point
  211. return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, via);
  212. }
  213. /**
  214. * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way
  215. * @param percentage
  216. * @param via
  217. * @returns {{x: number, y: number}}
  218. * @private
  219. */
  220. getPoint(percentage, via = this._getViaCoordinates()) {
  221. var t = percentage;
  222. var x = Math.pow(1 - t, 2) * this.from.x + (2 * t * (1 - t)) * via.x + Math.pow(t, 2) * this.to.x;
  223. var y = Math.pow(1 - t, 2) * this.from.y + (2 * t * (1 - t)) * via.y + Math.pow(t, 2) * this.to.y;
  224. return {x: x, y: y};
  225. }
  226. }
  227. export default BezierEdgeStatic;