UNPKG

visjs-network

Version:

A dynamic, browser-based network visualization library.

215 lines (192 loc) 5.74 kB
import BezierEdgeBase from './util/BezierEdgeBase' /** * A Static Bezier Edge. Bezier curves are used to model smooth gradual * curves in paths between nodes. * * @extends BezierEdgeBase */ class BezierEdgeStatic extends BezierEdgeBase { /** * @param {Object} options * @param {Object} body * @param {Label} labelModule */ constructor(options, body, labelModule) { super(options, body, labelModule) } /** * Draw a line between two nodes * @param {CanvasRenderingContext2D} ctx * @param {ArrowOptions} values * @param {Node} viaNode * @private */ _line(ctx, values, viaNode) { this._bezierCurve(ctx, values, viaNode) } /** * * @returns {Array.<{x: number, y: number}>} */ getViaNode() { return this._getViaCoordinates() } /** * We do not use the to and fromPoints here to make the via nodes the same as edges without arrows. * @returns {{x: undefined, y: undefined}} * @private */ _getViaCoordinates() { // Assumption: x/y coordinates in from/to always defined let xVia = undefined let yVia = undefined let factor = this.options.smooth.roundness let type = this.options.smooth.type let dx = Math.abs(this.from.x - this.to.x) let dy = Math.abs(this.from.y - this.to.y) if (type === 'discrete' || type === 'diagonalCross') { let stepX let stepY if (dx <= dy) { stepX = stepY = factor * dy } else { stepX = stepY = factor * dx } if (this.from.x > this.to.x) stepX = -stepX if (this.from.y >= this.to.y) stepY = -stepY xVia = this.from.x + stepX yVia = this.from.y + stepY if (type === 'discrete') { if (dx <= dy) { xVia = dx < factor * dy ? this.from.x : xVia } else { yVia = dy < factor * dx ? this.from.y : yVia } } } else if (type === 'straightCross') { let stepX = (1 - factor) * dx let stepY = (1 - factor) * dy if (dx <= dy) { // up - down stepX = 0 if (this.from.y < this.to.y) stepY = -stepY } else { // left - right if (this.from.x < this.to.x) stepX = -stepX stepY = 0 } xVia = this.to.x + stepX yVia = this.to.y + stepY } else if (type === 'horizontal') { let stepX = (1 - factor) * dx if (this.from.x < this.to.x) stepX = -stepX xVia = this.to.x + stepX yVia = this.from.y } else if (type === 'vertical') { let stepY = (1 - factor) * dy if (this.from.y < this.to.y) stepY = -stepY xVia = this.from.x yVia = this.to.y + stepY } else if (type === 'curvedCW') { dx = this.to.x - this.from.x dy = this.from.y - this.to.y let radius = Math.sqrt(dx * dx + dy * dy) let pi = Math.PI let originalAngle = Math.atan2(dy, dx) let myAngle = (originalAngle + (factor * 0.5 + 0.5) * pi) % (2 * pi) xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle) yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle) } else if (type === 'curvedCCW') { dx = this.to.x - this.from.x dy = this.from.y - this.to.y let radius = Math.sqrt(dx * dx + dy * dy) let pi = Math.PI let originalAngle = Math.atan2(dy, dx) let myAngle = (originalAngle + (-factor * 0.5 + 0.5) * pi) % (2 * pi) xVia = this.from.x + (factor * 0.5 + 0.5) * radius * Math.sin(myAngle) yVia = this.from.y + (factor * 0.5 + 0.5) * radius * Math.cos(myAngle) } else { // continuous let stepX let stepY if (dx <= dy) { stepX = stepY = factor * dy } else { stepX = stepY = factor * dx } if (this.from.x > this.to.x) stepX = -stepX if (this.from.y >= this.to.y) stepY = -stepY xVia = this.from.x + stepX yVia = this.from.y + stepY if (dx <= dy) { if (this.from.x <= this.to.x) { xVia = this.to.x < xVia ? this.to.x : xVia } else { xVia = this.to.x > xVia ? this.to.x : xVia } } else { if (this.from.y >= this.to.y) { yVia = this.to.y > yVia ? this.to.y : yVia } else { yVia = this.to.y < yVia ? this.to.y : yVia } } } return { x: xVia, y: yVia } } /** * * @param {Node} nearNode * @param {CanvasRenderingContext2D} ctx * @param {Object} options * @returns {*} * @private */ _findBorderPosition(nearNode, ctx, options = {}) { return this._findBorderPositionBezier(nearNode, ctx, options.via) } /** * * @param {number} x1 * @param {number} y1 * @param {number} x2 * @param {number} y2 * @param {number} x3 * @param {number} y3 * @param {Node} viaNode * @returns {number} * @private */ _getDistanceToEdge( x1, y1, x2, y2, x3, y3, viaNode = this._getViaCoordinates() ) { // x3,y3 is the point return this._getDistanceToBezierEdge(x1, y1, x2, y2, x3, y3, viaNode) } /** * Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way * @param {number} percentage * @param {Node} viaNode * @returns {{x: number, y: number}} * @private */ getPoint(percentage, viaNode = this._getViaCoordinates()) { var t = percentage var x = Math.pow(1 - t, 2) * this.fromPoint.x + 2 * t * (1 - t) * viaNode.x + Math.pow(t, 2) * this.toPoint.x var y = Math.pow(1 - t, 2) * this.fromPoint.y + 2 * t * (1 - t) * viaNode.y + Math.pow(t, 2) * this.toPoint.y return { x: x, y: y } } } export default BezierEdgeStatic