diff --git a/docs-kr/network/edges.html b/docs-kr/network/edges.html
index 46a70188ed..9437a4ae2c 100644
--- a/docs-kr/network/edges.html
+++ b/docs-kr/network/edges.html
@@ -204,6 +204,10 @@
옵션
},
selectionWidth: 1,
selfReferenceSize:20,
+ selfReference:{
+ size: 20,
+ angle: Math.PI / 4
+ },
shadow:{
enabled: false,
color: 'rgba(0,0,0,0.5)',
@@ -886,6 +890,27 @@ 옵션
false |
to Node와 from Node가 동일한 경우, 원이 그려집니다. 이것은 그 원의 반지름입니다. |
+
+ selfReference |
+ Object |
+ Object |
+ TODO
+ |
+
+
+ selfReference.size |
+ Number |
+ 20 |
+ TODO
+ |
+
+
+ selfReference.angle |
+ Number |
+ π / 4 |
+ TODO
+ |
+
shadow |
Object or Boolean |
diff --git a/docs/network/edges.html b/docs/network/edges.html
index 11dcc4bc1d..1bcaecbe3f 100644
--- a/docs/network/edges.html
+++ b/docs/network/edges.html
@@ -203,7 +203,11 @@ Options
}
},
selectionWidth: 1,
- selfReferenceSize:20,
+ selfReferenceSize: 20,
+ selfReference:{
+ size: 20,
+ angle: Math.PI / 4
+ },
shadow:{
enabled: false,
color: 'rgba(0,0,0,0.5)',
@@ -895,7 +899,31 @@ Options
selfReferenceSize |
Number |
false |
- When the to and from nodes are the same, a circle is drawn. This is the radius of that circle. |
+ When the to and from nodes are the same, a circle is drawn. This is the radius of that circle.
+ This property is deprecated please use selfReference instead.
+ |
+
+
+ selfReference |
+ Object |
+ Object |
+ When the to and from nodes are the same, a circle is drawn. This provides radius of circle and position.
+ |
+
+
+ selfReference.size |
+ Number |
+ 20 |
+ This is the radius of circle.
+ |
+
+
+ selfReference.angle |
+ Number |
+ π / 4 |
+ This is the angle (Provided in radians) to indicate position for the circle. If position is not provided then it will
+ be top-right (π / 4) corner.
+ |
shadow |
diff --git a/examples/network/edgeStyles/selfReference.html b/examples/network/edgeStyles/selfReference.html
new file mode 100644
index 0000000000..7fb2eccf77
--- /dev/null
+++ b/examples/network/edgeStyles/selfReference.html
@@ -0,0 +1,84 @@
+
+
+
+
+ Vis Network | Edge Styles | Self Reference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lib/network/modules/EdgesHandler.js b/lib/network/modules/EdgesHandler.js
index 3faa6c2873..32d5de5e28 100644
--- a/lib/network/modules/EdgesHandler.js
+++ b/lib/network/modules/EdgesHandler.js
@@ -94,7 +94,10 @@ class EdgesHandler {
}
},
selectionWidth: 1.5,
- selfReferenceSize:20,
+ selfReference: {
+ size: 20,
+ angle: Math.PI / 4,
+ },
shadow:{
enabled: false,
color: 'rgba(0,0,0,0.5)',
diff --git a/lib/network/modules/components/Edge.js b/lib/network/modules/components/Edge.js
index 6e55885e92..45892d3e25 100644
--- a/lib/network/modules/components/Edge.js
+++ b/lib/network/modules/components/Edge.js
@@ -130,6 +130,7 @@ class Edge {
'scaling',
'selectionWidth',
'selfReferenceSize',
+ 'selfReference',
'to',
'title',
'value',
@@ -249,6 +250,15 @@ class Edge {
if (allowDeletion === true && newOptions.font === null) {
parentOptions.font = util.bridgeObject(globalOptions.font); // set the object back to the global options
}
+
+ if(newOptions.hasOwnProperty("selfReferenceSize")){
+ console.log('The selfReferenceSize property has been deprecated. Please use selfReference property instead. The selfReference can be set like thise selfReference:{size:30, angle:Math.PI / 4}');
+ parentOptions.selfReference = {
+ size: newOptions.selfReferenceSize,
+ angle: parentOptions.selfReference.angle
+ }
+ }
+
}
@@ -676,17 +686,22 @@ class Edge {
else {
// Ignore the orientations.
this.labelModule.pointToSelf = true;
- var x, y;
- var radius = this.options.selfReferenceSize;
- if (node1.shape.width > node1.shape.height) {
- x = node1.x + node1.shape.width * 0.5;
- y = node1.y - radius;
- }
- else {
- x = node1.x + radius;
- y = node1.y - node1.shape.height * 0.5;
- }
- point = this._pointOnCircle(x, y, radius, 0.125);
+
+ // get circle coordinates
+ const coordinates = ComponentUtil.getSelfRefCoordinates(
+ ctx,
+ this.options.selfReference.angle,
+ this.options.selfReference.size,
+ node1
+ );
+
+ point = this._pointOnCircle(
+ coordinates.x,
+ coordinates.y,
+ this.options.selfReference.size,
+ this.options.selfReference.angle
+ );
+
this.labelModule.draw(ctx, point.x, point.y, this.selected, this.hover);
}
}
@@ -796,12 +811,11 @@ class Edge {
* @param {number} x
* @param {number} y
* @param {number} radius
- * @param {number} percentage Value between 0 (line start) and 1 (line end)
+ * @param {number} angle
* @return {Object} point
* @private
*/
- _pointOnCircle(x, y, radius, percentage) {
- var angle = percentage * 2 * Math.PI;
+ _pointOnCircle(x, y, radius, angle) {
return {
x: x + radius * Math.cos(angle),
y: y - radius * Math.sin(angle)
diff --git a/lib/network/modules/components/edges/util/edge-base.ts b/lib/network/modules/components/edges/util/edge-base.ts
index 187f4783b9..813fe5656b 100644
--- a/lib/network/modules/components/edges/util/edge-base.ts
+++ b/lib/network/modules/components/edges/util/edge-base.ts
@@ -16,6 +16,7 @@ import {
VNode
} from "./types";
import { drawDashedLine } from "./shapes";
+import * as ComponentUtil from "./../../shared/ComponentUtil";
export interface FindBorderPositionOptions {
via: Via;
@@ -106,6 +107,7 @@ export abstract class EdgeBase implements EdgeType {
*/
public setOptions(options: EdgeOptions): void {
this.options = options;
+
this.from = this._body.nodes[this.options.from];
this.to = this._body.nodes[this.options.to];
this.id = this.options.id;
@@ -318,26 +320,23 @@ export abstract class EdgeBase implements EdgeType {
protected _getCircleData(
ctx?: CanvasRenderingContext2D
): [number, number, number] {
- let x: number;
- let y: number;
- const node = this.from;
- const radius = this.options.selfReferenceSize;
+ const radius = this.options.selfReference.size;
if (ctx !== undefined) {
- if (node.shape.width === undefined) {
- node.shape.resize(ctx);
+ if (this.from.shape.width === undefined) {
+ this.from.shape.resize(ctx);
}
}
// get circle coordinates
- if (node.shape.width > node.shape.height) {
- x = node.x + node.shape.width * 0.5;
- y = node.y - radius;
- } else {
- x = node.x + radius;
- y = node.y - node.shape.height * 0.5;
- }
- return [x, y, radius];
+ const coordinates = ComponentUtil.default.getSelfRefCoordinates(
+ ctx,
+ this.options.selfReference.angle,
+ radius,
+ this.from
+ );
+
+ return [coordinates.x, coordinates.y, radius];
}
/**
@@ -387,9 +386,10 @@ export abstract class EdgeBase implements EdgeType {
const direction = options.direction;
const maxIterations = 10;
- const radius = this.options.selfReferenceSize;
+ const radius = this.options.selfReference.size;
const threshold = 0.05;
let pos: Point;
+
let middle = (low + high) * 0.5;
let iteration = 0;
@@ -746,28 +746,35 @@ export abstract class EdgeBase implements EdgeType {
const [x, y, radius] = this._getCircleData(ctx);
if (position === "from") {
+ const low = this.options.selfReference.angle - 2 * Math.PI;
+ const high = this.options.selfReference.angle;
+
const pointT = this._findBorderPositionCircle(this.from, ctx, {
x,
y,
- low: 0.25,
- high: 0.6,
+ low,
+ high,
direction: -1
});
angle = pointT.t * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI;
arrowPoint = pointT;
} else if (position === "to") {
+ const low = this.options.selfReference.angle - 2 * Math.PI;
+ const high = this.options.selfReference.angle;
+
const pointT = this._findBorderPositionCircle(this.from, ctx, {
x,
y,
- low: 0.6,
- high: 1.0,
+ low,
+ high,
direction: 1
});
angle = pointT.t * -2 * Math.PI + 1.5 * Math.PI - 1.1 * Math.PI;
arrowPoint = pointT;
} else {
- arrowPoint = this._pointOnCircle(x, y, radius, 0.175);
- angle = 3.9269908169872414; // === 0.175 * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI;
+ const pos = this.options.selfReference.angle / (2 * Math.PI);
+ arrowPoint = this._pointOnCircle(x, y, radius, pos);
+ angle = pos * -2 * Math.PI + 1.5 * Math.PI + 0.1 * Math.PI;
}
}
diff --git a/lib/network/modules/components/shared/ComponentUtil.js b/lib/network/modules/components/shared/ComponentUtil.js
index bbaafe01cd..43b2f7b96d 100644
--- a/lib/network/modules/components/shared/ComponentUtil.js
+++ b/lib/network/modules/components/shared/ComponentUtil.js
@@ -114,6 +114,54 @@ class ComponentUtil {
// Note that this is quite strict: types that *might* be converted to string are disallowed
return (typeof text === 'string' && text !== '');
}
+
+ /**
+ * Returns x, y of self reference circle based on provided angle
+ *
+ * @param {Object} ctx
+ * @param {number} angle
+ * @param {number} radius
+ * @return {Object} node
+ * @returns {Object} x and y coordinates
+ */
+ static getSelfRefCoordinates(ctx, angle, radius, node){
+ let x = node.x;
+ let y = node.y;
+
+ if(ctx && typeof node.distanceToBorder === "function"){
+ //calculating opposite and adjacent
+ //distaneToBorder becomes Hypotenuse.
+ //Formulas sin(a) = Opposite / Hypotenuse and cos(a) = Adjacent / Hypotenuse
+ const toBorderDist = node.distanceToBorder(ctx, angle);
+ const yFromNodeCenter = Math.sin(angle)*toBorderDist;
+ const xFromNodeCenter = Math.cos(angle)*toBorderDist;
+ //xFromNodeCenter is basically x and if xFromNodeCenter equals to the distance to border then it means
+ //that y does not need calculation because it is equal node.height / 2 or node.y
+ //same thing with yFromNodeCenter and if yFromNodeCenter equals to the distance to border then it means
+ //that x is equal node.width / 2 or node.x
+ if(xFromNodeCenter === toBorderDist){
+ x += toBorderDist;
+ y = node.y;
+ }else if(yFromNodeCenter === toBorderDist){
+ x = node.x;
+ y -= toBorderDist;
+ }else{
+ x += xFromNodeCenter;
+ y -= yFromNodeCenter;
+ }
+
+
+ } else if (node.shape.width > node.shape.height) {
+ x = node.x + node.shape.width * 0.5;
+ y = node.y - radius;
+ } else {
+ x = node.x + radius;
+ y = node.y - node.shape.height * 0.5;
+ }
+
+ return {x,y};
+ }
+
}
-export default ComponentUtil;
+export default ComponentUtil;
\ No newline at end of file
diff --git a/lib/network/options.js b/lib/network/options.js
index f0aed6e50a..6baf4e7d10 100644
--- a/lib/network/options.js
+++ b/lib/network/options.js
@@ -156,6 +156,11 @@ let allOptions = {
},
selectionWidth: { 'function': 'function', number },
selfReferenceSize: { number },
+ selfReference: {
+ size: { number },
+ angle: { number },
+ __type__: { object }
+ },
shadow: {
enabled: { boolean: bool },
color: { string },
@@ -580,6 +585,10 @@ let configureOptions = {
},
selectionWidth: [1.5, 0, 5, 0.1],
selfReferenceSize: [20, 0, 200, 1],
+ selfReference: {
+ size: [20, 0, 200, 1],
+ angle: [Math.PI / 2, Math.PI * 2, 3 * Math.PI / 2, Math.PI],
+ },
shadow: {
enabled: false,
color: 'rgba(0,0,0,0.5)',
diff --git a/test/edges/bezier-edge-dynamic.test.ts b/test/edges/bezier-edge-dynamic.test.ts
index f966d05cfd..7a19eea2b3 100644
--- a/test/edges/bezier-edge-dynamic.test.ts
+++ b/test/edges/bezier-edge-dynamic.test.ts
@@ -239,7 +239,10 @@ describe('BezierEdgeDynamic', function(): void {
smooth: {
roundness: 2,
},
- selfReferenceSize: 2,
+ selfReference: {
+ size: 2,
+ angle: Math.PI / 2,
+ },
},
body,
{} as any
diff --git a/test/edges/cubic-bezier-edge.test.ts b/test/edges/cubic-bezier-edge.test.ts
index 9394034745..884a8862a8 100644
--- a/test/edges/cubic-bezier-edge.test.ts
+++ b/test/edges/cubic-bezier-edge.test.ts
@@ -146,7 +146,10 @@ describe('CubicBezierEdge', function(): void {
smooth: {
roundness: 2,
},
- selfReferenceSize: 42,
+ selfReference: {
+ size: 42,
+ angle: Math.PI / 2,
+ },
},
body as any,
{} as any
@@ -511,14 +514,14 @@ describe('CubicBezierEdge', function(): void {
to: 4,
expected: {
from: {
- t: 0.250341796875,
- x: 420.9098019990056,
- y: -483.99990314656236,
+ t: 0.5077148437499999,
+ x: 358.049334219333,
+ y: -841.9648978996685,
},
to: {
t: 0.7998046875,
- x: 433.92968488174444,
- y: -402.0397291193016,
+ x: 412.92968488174444,
+ y: -804.0397291193017,
},
},
},
@@ -535,7 +538,10 @@ describe('CubicBezierEdge', function(): void {
smooth: {
roundness: 2,
},
- selfReferenceSize: 42,
+ selfReference: {
+ size: 42,
+ angle: Math.PI / 2,
+ },
},
body,
{} as any
@@ -559,16 +565,16 @@ describe('CubicBezierEdge', function(): void {
},
position: 'from',
expected: {
- angle: 3.4536043458457324,
+ angle: 1.9037437282114893,
core: {
- x: 447.9532857144876,
- y: -417.2972622260487,
+ x: 396.26792442306333,
+ y: -871.0373387250717,
},
length: 31.5,
point: {
- t: 0.250341796875,
- x: 420.9720815711208,
- y: -425.999970021555,
+ t: 0.4970097752749478,
+ x: 387.0022943938739,
+ y: -844.2442313994518,
},
type: 'arrow',
},
@@ -584,15 +590,15 @@ describe('CubicBezierEdge', function(): void {
},
position: 'middle',
expected: {
- angle: 3.9269908169872414,
+ angle: 3.4557519189487724,
core: {
- x: 447.9029478978546,
- y: -403.58201341320836,
+ x: 428.24637853396604,
+ y: -847.8221952670641,
},
length: 33,
point: {
- x: 426.90187649661414,
- y: -424.5830848144488,
+ x: 400,
+ y: -857,
},
type: 'bar',
},
@@ -608,16 +614,16 @@ describe('CubicBezierEdge', function(): void {
},
position: 'to',
expected: {
- angle: -5.024093876483052,
+ angle: 13.863514558139903,
core: {
- x: 424.06346980869967,
- y: -443.80680503833094,
+ x: 404.23324559789233,
+ y: -874.6679591046823,
},
length: 36,
point: {
- t: 0.999609375,
- x: 433.99996084448463,
- y: -412.96809323164604,
+ t: -2.006446870554419,
+ x: 412.9893362093595,
+ y: -843.4735545230305,
},
type: 'circle',
},
@@ -741,7 +747,10 @@ describe('CubicBezierEdge', function(): void {
enabled: smooth,
roundness: 2,
},
- selfReferenceSize: 13,
+ selfReference: {
+ size: 13,
+ angle: Math.PI / 2,
+ },
},
body,
{} as any
diff --git a/types/network/Network.d.ts b/types/network/Network.d.ts
index 3be7d045b9..0c67caeff4 100644
--- a/types/network/Network.d.ts
+++ b/types/network/Network.d.ts
@@ -968,6 +968,11 @@ export interface EdgeOptions {
selfReferenceSize?: number;
+ selfReference?: {
+ size?: number,
+ angle?: number,
+ };
+
shadow?: boolean | OptionsShadow;
smooth?: boolean | {