|
|
@ -27437,7 +27437,7 @@ return /******/ (function(modules) { // webpackBootstrap |
|
|
|
*/ |
|
|
|
value: function draw(ctx) { |
|
|
|
var via = this.drawLine(ctx); |
|
|
|
this.drawArrows(ctx); |
|
|
|
this.drawArrows(ctx, via); |
|
|
|
this.drawLabel(ctx, via); |
|
|
|
}, |
|
|
|
writable: true, |
|
|
@ -27455,13 +27455,15 @@ return /******/ (function(modules) { // webpackBootstrap |
|
|
|
configurable: true |
|
|
|
}, |
|
|
|
drawArrows: { |
|
|
|
value: function drawArrows(ctx) { |
|
|
|
value: function drawArrows(ctx, viaNode) { |
|
|
|
if (this.options.arrows.from.enabled === true) { |
|
|
|
this._drawArrowHead(ctx, "from"); |
|
|
|
this._drawArrowHead(ctx, "from", viaNode); |
|
|
|
} |
|
|
|
if (this.options.arrows.middle.enabled === true) { |
|
|
|
this._drawArrowHead(ctx, "middle", viaNode); |
|
|
|
} |
|
|
|
//if (this.options.arrows.middle.enabled === true) {this._drawArrowCenter(ctx, via);}
|
|
|
|
if (this.options.arrows.to.enabled === true) { |
|
|
|
this._drawArrowHead(ctx, "to"); |
|
|
|
this._drawArrowHead(ctx, "to", viaNode); |
|
|
|
} |
|
|
|
|
|
|
|
}, |
|
|
@ -27469,20 +27471,13 @@ return /******/ (function(modules) { // webpackBootstrap |
|
|
|
configurable: true |
|
|
|
}, |
|
|
|
drawLabel: { |
|
|
|
value: function drawLabel(ctx, via) { |
|
|
|
value: function drawLabel(ctx, viaNode) { |
|
|
|
if (this.label !== undefined) { |
|
|
|
// set style
|
|
|
|
var node1 = this.from; |
|
|
|
var node2 = this.to; |
|
|
|
if (node1.id != node2.id) { |
|
|
|
var point; |
|
|
|
if (this.options.smooth.enabled == true && via != undefined) { |
|
|
|
var midpointX = 0.5 * (0.5 * (this.from.x + via.x) + 0.5 * (this.to.x + via.x)); |
|
|
|
var midpointY = 0.5 * (0.5 * (this.from.y + via.y) + 0.5 * (this.to.y + via.y)); |
|
|
|
point = { x: midpointX, y: midpointY }; |
|
|
|
} else { |
|
|
|
point = this._pointOnLine(0.5); |
|
|
|
} |
|
|
|
var point = this._pointOnEdge(0.5, viaNode); |
|
|
|
this._label(ctx, this.label, point.x, point.y); |
|
|
|
} else { |
|
|
|
var x, y; |
|
|
@ -28101,27 +28096,36 @@ return /******/ (function(modules) { // webpackBootstrap |
|
|
|
writable: true, |
|
|
|
configurable: true |
|
|
|
}, |
|
|
|
_pointOnLine: { |
|
|
|
_pointOnEdge: { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Get a point on a line |
|
|
|
* @param {Number} percentage. Value between 0 (line start) and 1 (line end) |
|
|
|
* @return {Object} point |
|
|
|
* Combined function of pointOnLine and pointOnBezier. This gives the coordinates of a point on the line at a certain percentage of the way |
|
|
|
* @param percentage |
|
|
|
* @param via |
|
|
|
* @returns {{x: number, y: number}} |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
value: function _pointOnLine(percentage) { |
|
|
|
return { |
|
|
|
x: (1 - percentage) * this.from.x + percentage * this.to.x, |
|
|
|
y: (1 - percentage) * this.from.y + percentage * this.to.y |
|
|
|
}; |
|
|
|
value: function _pointOnEdge(percentage) { |
|
|
|
var via = arguments[1] === undefined ? this._getViaCoordinates() : arguments[1]; |
|
|
|
if (this.options.smooth.enabled == false) { |
|
|
|
return { |
|
|
|
x: (1 - percentage) * this.from.x + percentage * this.to.x, |
|
|
|
y: (1 - percentage) * this.from.y + percentage * this.to.y |
|
|
|
}; |
|
|
|
} else { |
|
|
|
var t = percentage; |
|
|
|
var x = Math.pow(1 - t, 2) * this.from.x + 2 * t * (1 - t) * via.x + Math.pow(t, 2) * this.to.x; |
|
|
|
var y = Math.pow(1 - t, 2) * this.from.y + 2 * t * (1 - t) * via.y + Math.pow(t, 2) * this.to.y; |
|
|
|
|
|
|
|
return { x: x, y: y }; |
|
|
|
} |
|
|
|
}, |
|
|
|
writable: true, |
|
|
|
configurable: true |
|
|
|
}, |
|
|
|
_pointOnCircle: { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Get a point on a circle |
|
|
|
* @param {Number} x |
|
|
@ -28141,93 +28145,6 @@ return /******/ (function(modules) { // webpackBootstrap |
|
|
|
writable: true, |
|
|
|
configurable: true |
|
|
|
}, |
|
|
|
_drawArrowCenter: { |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* Redraw a edge as a line with an arrow halfway the line |
|
|
|
* Draw this edge in the given canvas |
|
|
|
* The 2d context of a HTML canvas can be retrieved by canvas.getContext("2d"); |
|
|
|
* @param {CanvasRenderingContext2D} ctx |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
value: function _drawArrowCenter(ctx) { |
|
|
|
var point; |
|
|
|
// set style
|
|
|
|
ctx.strokeStyle = this._getColor(ctx); |
|
|
|
ctx.fillStyle = ctx.strokeStyle; |
|
|
|
ctx.lineWidth = this._getLineWidth(); |
|
|
|
|
|
|
|
if (this.from != this.to) { |
|
|
|
// draw line
|
|
|
|
var via = this._line(ctx); |
|
|
|
|
|
|
|
var angle = Math.atan2(this.to.y - this.from.y, this.to.x - this.from.x); |
|
|
|
var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; |
|
|
|
// draw an arrow halfway the line
|
|
|
|
if (this.options.smooth.enabled == true && via != undefined) { |
|
|
|
var midpointX = 0.5 * (0.5 * (this.from.x + via.x) + 0.5 * (this.to.x + via.x)); |
|
|
|
var midpointY = 0.5 * (0.5 * (this.from.y + via.y) + 0.5 * (this.to.y + via.y)); |
|
|
|
point = { x: midpointX, y: midpointY }; |
|
|
|
} else { |
|
|
|
point = this._pointOnLine(0.5); |
|
|
|
} |
|
|
|
|
|
|
|
ctx.arrow(point.x, point.y, angle, length); |
|
|
|
ctx.fill(); |
|
|
|
ctx.stroke(); |
|
|
|
|
|
|
|
// draw label
|
|
|
|
if (this.label) { |
|
|
|
this._label(ctx, this.label, point.x, point.y); |
|
|
|
} |
|
|
|
} else { |
|
|
|
// draw circle
|
|
|
|
var x, y; |
|
|
|
var radius = 25; |
|
|
|
var node = this.from; |
|
|
|
if (!node.width) { |
|
|
|
node.resize(ctx); |
|
|
|
} |
|
|
|
if (node.width > node.height) { |
|
|
|
x = node.x + node.width * 0.5; |
|
|
|
y = node.y - radius; |
|
|
|
} else { |
|
|
|
x = node.x + radius; |
|
|
|
y = node.y - node.height * 0.5; |
|
|
|
} |
|
|
|
this._circle(ctx, x, y, radius); |
|
|
|
|
|
|
|
// draw all arrows
|
|
|
|
var angle = 0.2 * Math.PI; |
|
|
|
var length = (10 + 5 * this.options.width) * this.options.arrowScaleFactor; |
|
|
|
point = this._pointOnCircle(x, y, radius, 0.5); |
|
|
|
ctx.arrow(point.x, point.y, angle, length); |
|
|
|
ctx.fill(); |
|
|
|
ctx.stroke(); |
|
|
|
|
|
|
|
// draw label
|
|
|
|
if (this.label) { |
|
|
|
point = this._pointOnCircle(x, y, radius, 0.5); |
|
|
|
this._label(ctx, this.label, point.x, point.y); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
writable: true, |
|
|
|
configurable: true |
|
|
|
}, |
|
|
|
_pointOnBezier: { |
|
|
|
value: function _pointOnBezier(t) { |
|
|
|
var via = this._getViaCoordinates(); |
|
|
|
|
|
|
|
var x = Math.pow(1 - t, 2) * this.from.x + 2 * t * (1 - t) * via.x + Math.pow(t, 2) * this.to.x; |
|
|
|
var y = Math.pow(1 - t, 2) * this.from.y + 2 * t * (1 - t) * via.y + Math.pow(t, 2) * this.to.y; |
|
|
|
|
|
|
|
return { x: x, y: y }; |
|
|
|
}, |
|
|
|
writable: true, |
|
|
|
configurable: true |
|
|
|
}, |
|
|
|
_findBorderPositionBezier: { |
|
|
|
|
|
|
|
/** |
|
|
@ -28238,6 +28155,7 @@ return /******/ (function(modules) { // webpackBootstrap |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
value: function _findBorderPositionBezier(nearNode, ctx) { |
|
|
|
var viaNode = arguments[2] === undefined ? this._getViaCoordinates() : arguments[2]; |
|
|
|
var maxIterations = 10; |
|
|
|
var iteration = 0; |
|
|
|
var low = 0; |
|
|
@ -28254,7 +28172,7 @@ return /******/ (function(modules) { // webpackBootstrap |
|
|
|
while (low <= high && iteration < maxIterations) { |
|
|
|
var middle = (low + high) * 0.5; |
|
|
|
|
|
|
|
pos = this._pointOnBezier(middle); |
|
|
|
pos = this._pointOnEdge(middle, viaNode); |
|
|
|
angle = Math.atan2(node.y - pos.y, node.x - pos.x); |
|
|
|
distanceToBorder = node.distanceToBorder(ctx, angle); |
|
|
|
distanceToPoint = Math.sqrt(Math.pow(pos.x - node.x, 2) + Math.pow(pos.y - node.y, 2)); |
|
|
@ -28344,7 +28262,7 @@ return /******/ (function(modules) { // webpackBootstrap |
|
|
|
* @param guideOffset |
|
|
|
* @private |
|
|
|
*/ |
|
|
|
value: function _drawArrowHead(ctx, position) { |
|
|
|
value: function _drawArrowHead(ctx, position, viaNode) { |
|
|
|
// set style
|
|
|
|
ctx.strokeStyle = this._getColor(ctx); |
|
|
|
ctx.fillStyle = ctx.strokeStyle; |
|
|
@ -28369,28 +28287,36 @@ return /******/ (function(modules) { // webpackBootstrap |
|
|
|
node2 = this.from; |
|
|
|
guideOffset = -0.1; |
|
|
|
scaleFactor = this.options.arrows.to.scaleFactor; |
|
|
|
} else { |
|
|
|
node1 = this.to; |
|
|
|
node2 = this.from; |
|
|
|
scaleFactor = this.options.arrows.middle.scaleFactor; |
|
|
|
} |
|
|
|
|
|
|
|
// if not connected to itself
|
|
|
|
if (node1 != node2) { |
|
|
|
// draw arrow head
|
|
|
|
if (this.options.smooth.enabled == true) { |
|
|
|
arrowPos = this._findBorderPositionBezier(node1, ctx); |
|
|
|
var guidePos = this._pointOnBezier(Math.max(0, arrowPos.t + guideOffset)); |
|
|
|
angle = Math.atan2(arrowPos.y - guidePos.y, arrowPos.x - guidePos.x); |
|
|
|
if (position !== "middle") { |
|
|
|
// draw arrow head
|
|
|
|
if (this.options.smooth.enabled == true) { |
|
|
|
arrowPos = this._findBorderPositionBezier(node1, ctx, viaNode); |
|
|
|
var guidePos = this._pointOnEdge(Math.max(0, Math.min(1, arrowPos.t + guideOffset)), viaNode); |
|
|
|
angle = Math.atan2(arrowPos.y - guidePos.y, arrowPos.x - guidePos.x); |
|
|
|
} else { |
|
|
|
angle = Math.atan2(node1.y - node2.y, node1.x - node2.x); |
|
|
|
var dx = node1.x - node2.x; |
|
|
|
var dy = node1.y - node2.y; |
|
|
|
var edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); |
|
|
|
var toBorderDist = this.to.distanceToBorder(ctx, angle); |
|
|
|
var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; |
|
|
|
|
|
|
|
arrowPos = {}; |
|
|
|
arrowPos.x = (1 - toBorderPoint) * node2.x + toBorderPoint * node1.x; |
|
|
|
arrowPos.y = (1 - toBorderPoint) * node2.y + toBorderPoint * node1.y; |
|
|
|
} |
|
|
|
} else { |
|
|
|
angle = Math.atan2(node1.y - node2.y, node1.x - node2.x); |
|
|
|
var dx = node1.x - node2.x; |
|
|
|
var dy = node1.y - node2.y; |
|
|
|
var edgeSegmentLength = Math.sqrt(dx * dx + dy * dy); |
|
|
|
var toBorderDist = this.to.distanceToBorder(ctx, angle); |
|
|
|
var toBorderPoint = (edgeSegmentLength - toBorderDist) / edgeSegmentLength; |
|
|
|
|
|
|
|
arrowPos = {}; |
|
|
|
arrowPos.x = (1 - toBorderPoint) * node2.x + toBorderPoint * node1.x; |
|
|
|
arrowPos.y = (1 - toBorderPoint) * node2.y + toBorderPoint * node1.y; |
|
|
|
arrowPos = this._pointOnEdge(0.6, viaNode); // this is 0.6 to account for the size of the arrow.
|
|
|
|
} |
|
|
|
|
|
|
|
// draw arrow at the end of the line
|
|
|
|
length = (10 + 5 * this.options.width) * scaleFactor; |
|
|
|
ctx.arrow(arrowPos.x, arrowPos.y, angle, length); |
|
|
@ -28418,14 +28344,15 @@ return /******/ (function(modules) { // webpackBootstrap |
|
|
|
if (position == "from") { |
|
|
|
point = this._findBorderPositionCircle(x, y, radius, node1, 0.25, 0.6, -1, ctx); |
|
|
|
angle = point.t * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI; |
|
|
|
} else { |
|
|
|
} else if (position == "to") { |
|
|
|
point = this._findBorderPositionCircle(x, y, radius, node1, 0.6, 0.8, 1, ctx); |
|
|
|
angle = point.t * -2 * Math.PI + 1.5 * Math.PI - 1.1 * Math.PI; |
|
|
|
} else { |
|
|
|
point = this._pointOnCircle(x, y, radius, 0.175); |
|
|
|
angle = 3.9269908169872414; // == 0.175 * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI;
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// draw all arrows
|
|
|
|
// draw the arrowhead
|
|
|
|
var length = (10 + 5 * this.options.width) * scaleFactor; |
|
|
|
ctx.arrow(point.x, point.y, angle, length); |
|
|
|
ctx.fill(); |
|
|
|