Browse Source

Network: Consolidate code for generating endpoints (#3422)

* Moved endpoint-specific code to module EndPoints

* Further decomposed functionality for endpoints

* Added commenting, notably for typedef's

* Add next attempt at fixing travis bug
revert-3409-performance
wimrijnders 6 years ago
committed by Yotam Berkowitz
parent
commit
7157df08af
3 changed files with 180 additions and 57 deletions
  1. +3
    -7
      lib/network/modules/components/edges/util/EdgeBase.js
  2. +177
    -0
      lib/network/modules/components/edges/util/EndPoints.js
  3. +0
    -50
      lib/network/shapes.js

+ 3
- 7
lib/network/modules/components/edges/util/EdgeBase.js View File

@ -1,4 +1,6 @@
let util = require("../../../../../util");
let EndPoints = require("./EndPoints").default;
/**
* The Base Class for all edges.
@ -559,13 +561,7 @@ class EdgeBase {
ctx.fillStyle = ctx.strokeStyle;
ctx.lineWidth = values.width;
if (arrowData.type && arrowData.type.toLowerCase() === 'circle') {
// draw circle at the end of the line
ctx.circleEndpoint(arrowData.point.x, arrowData.point.y, arrowData.angle, arrowData.length);
} else {
// draw arrow at the end of the line
ctx.arrowEndpoint(arrowData.point.x, arrowData.point.y, arrowData.angle, arrowData.length);
}
EndPoints.draw(ctx, arrowData);
// draw shadow if enabled
this.enableShadow(ctx, values);

+ 177
- 0
lib/network/modules/components/edges/util/EndPoints.js View File

@ -0,0 +1,177 @@
/**
* Location of all the endpoint drawing routines.
*
* Every endpoint has its own drawing routine, which contains an endpoint definition.
*
* The endpoint definitions must have the following properies:
*
* - (0,0) is the connection point to the node it attaches to
* - The endpoints are orientated to the positive x-direction
* - The length of the endpoint is at most 1
*
* As long as the endpoint classes remain simple and not too numerous, they will be contained within this module.
* All classes here except `EndPoints` should be considered as private to this module.
*/
// NOTE: When a typedef is isolated in a separate comment block, an actual description is generated for it,
// using the rest of the commenting in the code block. Usage of typedef in other comments then
// link to there. TIL.
//
// Also noteworthy, all typedef's set up in this manner are collected in a single, global page 'global.html'.
// In other words, it doesn't matter *where* the typedef's are defined in the code.
//
//
// TODO: add descriptive commenting to given typedef's
/**
* @typedef {{type:string, point:Point, angle:number, length:number}} ArrowData
*
* Object containing instantiation data for a given endpoint.
*/
/**
* @typedef {{x:number, y:number}} Point
*
* A point in view-coordinates.
*/
/**
* Common methods for endpoints
*
* @class
*/
class EndPoint {
/**
* Apply transformation on points for display.
*
* The following is done:
* - rotate by the specified angle
* - multiply the (normalized) coordinates by the passed length
* - offset by the target coordinates
*
* @param {Array<Point>} points
* @param {ArrowData} arrowData
* @static
*/
static transform(points, arrowData) {
if (!(points instanceof Array)) {
points = [points];
}
var x = arrowData.point.x;
var y = arrowData.point.y;
var angle = arrowData.angle
var length = arrowData.length;
for(var i = 0; i < points.length; ++i) {
var p = points[i];
var xt = p.x * Math.cos(angle) - p.y * Math.sin(angle);
var yt = p.x * Math.sin(angle) + p.y * Math.cos(angle);
p.x = x + length*xt;
p.y = y + length*yt;
}
}
/**
* Draw a closed path using the given real coordinates.
*
* @param {CanvasRenderingContext2D} ctx
* @param {Array.<Point>} points
* @static
*/
static drawPath(ctx, points) {
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for(var i = 1; i < points.length; ++i) {
ctx.lineTo(points[i].x, points[i].y);
}
ctx.closePath();
}
}
/**
* Drawing methods for the arrow endpoint.
* @extends EndPoint
*/
class Arrow extends EndPoint {
/**
* Draw this shape at the end of a line.
*
* @param {CanvasRenderingContext2D} ctx
* @param {ArrowData} arrowData
* @static
*/
static draw(ctx, arrowData) {
// Normalized points of closed path, in the order that they should be drawn.
// (0, 0) is the attachment point, and the point around which should be rotated
var points = [
{ x: 0 , y: 0 },
{ x:-1 , y: 0.3},
{ x:-0.9, y: 0 },
{ x:-1 , y:-0.3},
];
EndPoint.transform(points, arrowData);
EndPoint.drawPath(ctx, points);
}
}
/**
* Drawing methods for the circle endpoint.
*/
class Circle {
/**
* Draw this shape at the end of a line.
*
* @param {CanvasRenderingContext2D} ctx
* @param {ArrowData} arrowData
* @static
*/
static draw(ctx, arrowData) {
var point = {x:-0.4, y:0};
EndPoint.transform(point, arrowData);
ctx.circle(point.x, point.y, arrowData.length*0.4);
}
}
/**
* Drawing methods for the endpoints.
*/
class EndPoints {
/**
* Draw an endpoint
*
* @param {CanvasRenderingContext2D} ctx
* @param {ArrowData} arrowData
* @static
*/
static draw(ctx, arrowData) {
var type;
if (arrowData.type) {
type = arrowData.type.toLowerCase();
}
switch (type) {
case 'circle':
Circle.draw(ctx, arrowData);
break;
case 'arrow': // fall-through
default:
Arrow.draw(ctx, arrowData);
}
}
}
export default EndPoints;

+ 0
- 50
lib/network/shapes.js View File

@ -227,54 +227,6 @@ if (typeof CanvasRenderingContext2D !== 'undefined') {
};
/**
* Draw an arrow at the end of a line with the given angle.
*
* @param {number} x
* @param {number} y
* @param {number} angle
* @param {number} length
*/
CanvasRenderingContext2D.prototype.arrowEndpoint = function (x, y, angle, length) {
// tail
var xt = x - length * Math.cos(angle);
var yt = y - length * Math.sin(angle);
// inner tail
var xi = x - length * 0.9 * Math.cos(angle);
var yi = y - length * 0.9 * Math.sin(angle);
// left
var xl = xt + length / 3 * Math.cos(angle + 0.5 * Math.PI);
var yl = yt + length / 3 * Math.sin(angle + 0.5 * Math.PI);
// right
var xr = xt + length / 3 * Math.cos(angle - 0.5 * Math.PI);
var yr = yt + length / 3 * Math.sin(angle - 0.5 * Math.PI);
this.beginPath();
this.moveTo(x, y);
this.lineTo(xl, yl);
this.lineTo(xi, yi);
this.lineTo(xr, yr);
this.closePath();
};
/**
* Draw an circle an the end of an line with the given angle.
*
* @param {number} x
* @param {number} y
* @param {number} angle
* @param {number} length
*/
CanvasRenderingContext2D.prototype.circleEndpoint = function (x, y, angle, length) {
var radius = length * 0.4;
var xc = x - radius * Math.cos(angle);
var yc = y - radius * Math.sin(angle);
this.circle(xc, yc, radius);
};
/**
* Sets up the dashedLine functionality for drawing
* Original code came from http://stackoverflow.com/questions/4576724/dotted-stroke-in-canvas
@ -336,6 +288,4 @@ if (typeof CanvasRenderingContext2D !== 'undefined') {
}
this.closePath();
};
}

Loading…
Cancel
Save