UNPKG

vis-network

Version:

A dynamic, browser-based visualization library.

137 lines (125 loc) 3.48 kB
import { CubicBezierEdgeBase } from "./util/cubic-bezier-edge-base"; import { EdgeFormattingValues, Label, EdgeOptions, Point, PointT, SelectiveRequired, VBody, VNode } from "./util/types"; /** * A Cubic Bezier Edge. Bezier curves are used to model smooth gradual curves in paths between nodes. */ export class CubicBezierEdge extends CubicBezierEdgeBase<[Point, Point]> { /** * Create a new instance. * * @param options - The options object of given edge. * @param body - The body of the network. * @param labelModule - Label module. */ public constructor(options: EdgeOptions, body: VBody, labelModule: Label) { super(options, body, labelModule); } /** @inheritdoc */ protected _line( ctx: CanvasRenderingContext2D, values: SelectiveRequired< EdgeFormattingValues, | "backgroundColor" | "backgroundSize" | "shadowColor" | "shadowSize" | "shadowX" | "shadowY" >, viaNodes: [Point, Point] ): void { // get the coordinates of the support points. let via1 = viaNodes[0]; let via2 = viaNodes[1]; this._bezierCurve(ctx, values, via1, via2); } /** * Compute the additional points the edge passes through. * * @returns Cartesian coordinates of the points the edge passes through. */ protected _getViaCoordinates(): [Point, Point] { const dx = this.from.x - this.to.x; const dy = this.from.y - this.to.y; let x1: number; let y1: number; let x2: number; let y2: number; const roundness = this.options.smooth.roundness; // horizontal if x > y or if direction is forced or if direction is horizontal if ( (Math.abs(dx) > Math.abs(dy) || this.options.smooth.forceDirection === true || this.options.smooth.forceDirection === "horizontal") && this.options.smooth.forceDirection !== "vertical" ) { y1 = this.from.y; y2 = this.to.y; x1 = this.from.x - roundness * dx; x2 = this.to.x + roundness * dx; } else { y1 = this.from.y - roundness * dy; y2 = this.to.y + roundness * dy; x1 = this.from.x; x2 = this.to.x; } return [{ x: x1, y: y1 }, { x: x2, y: y2 }]; } /** @inheritdoc */ public getViaNode(): [Point, Point] { return this._getViaCoordinates(); } /** @inheritdoc */ protected _findBorderPosition( nearNode: VNode, ctx: CanvasRenderingContext2D ): PointT { return this._findBorderPositionBezier(nearNode, ctx); } /** @inheritdoc */ protected _getDistanceToEdge( x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, [via1, via2]: [Point, Point] = this._getViaCoordinates() ): number { // x3,y3 is the point return this._getDistanceToBezierEdge2(x1, y1, x2, y2, x3, y3, via1, via2); } /** @inheritdoc */ public getPoint( position: number, [via1, via2]: [Point, Point] = this._getViaCoordinates() ): Point { const t = position; const vec: [number, number, number, number] = [ Math.pow(1 - t, 3), 3 * t * Math.pow(1 - t, 2), 3 * Math.pow(t, 2) * (1 - t), Math.pow(t, 3) ]; const x = vec[0] * this.fromPoint.x + vec[1] * via1.x + vec[2] * via2.x + vec[3] * this.toPoint.x; const y = vec[0] * this.fromPoint.y + vec[1] * via1.y + vec[2] * via2.y + vec[3] * this.toPoint.y; return { x: x, y: y }; } }