@react-fabric/graph 1.0.0-beta.58
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +10 -0
- package/css/styles.css +56 -0
- package/dist/cjs/_virtual/_commonjs-dynamic-modules.js +7 -0
- package/dist/cjs/_virtual/_commonjsHelpers.js +7 -0
- package/dist/cjs/_virtual/_rollup-plugin-web-worker-loader__helper__auto__createBase64WorkerFactory.js +14 -0
- package/dist/cjs/_virtual/_rollup-plugin-web-worker-loader__helper__auto__isNodeJS.js +9 -0
- package/dist/cjs/_virtual/_rollup-plugin-web-worker-loader__helper__browser__createBase64WorkerFactory.js +35 -0
- package/dist/cjs/_virtual/_rollup-plugin-web-worker-loader__helper__node__WorkerClass.js +11 -0
- package/dist/cjs/_virtual/_rollup-plugin-web-worker-loader__helper__node__createBase64WorkerFactory.js +20 -0
- package/dist/cjs/_virtual/elk-worker.js +8 -0
- package/dist/cjs/_virtual/elk.bundled.js +5 -0
- package/dist/cjs/node_modules/elkjs/lib/elk.bundled.js +6667 -0
- package/dist/cjs/packages/graph/src/components/Context.js +108 -0
- package/dist/cjs/packages/graph/src/components/ContextMenu.js +134 -0
- package/dist/cjs/packages/graph/src/components/Tools.js +127 -0
- package/dist/cjs/packages/graph/src/components/Viewer.js +57 -0
- package/dist/cjs/packages/graph/src/constants/index.js +16 -0
- package/dist/cjs/packages/graph/src/graph/index.js +425 -0
- package/dist/cjs/packages/graph/src/hooks/sigmaDragSelect.js +169 -0
- package/dist/cjs/packages/graph/src/hooks/sigmaHilighter.js +83 -0
- package/dist/cjs/packages/graph/src/hooks/sigmaMouseActions.js +145 -0
- package/dist/cjs/packages/graph/src/hooks/useGraphology.js +41 -0
- package/dist/cjs/packages/graph/src/hooks/useSigma.js +112 -0
- package/dist/cjs/packages/graph/src/index.js +33 -0
- package/dist/cjs/packages/graph/src/programs/arrow-head/frag.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/arrow-head/index.js +142 -0
- package/dist/cjs/packages/graph/src/programs/arrow-head/vert.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/edge-curve/drawLabel.js +136 -0
- package/dist/cjs/packages/graph/src/programs/edge-curve/frag.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/edge-curve/index.js +157 -0
- package/dist/cjs/packages/graph/src/programs/edge-curve/vert.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/edge-line/drawLabel.js +70 -0
- package/dist/cjs/packages/graph/src/programs/edge-line/frag.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/edge-line/index.js +166 -0
- package/dist/cjs/packages/graph/src/programs/edge-line/vert.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/node-badge/factory.js +249 -0
- package/dist/cjs/packages/graph/src/programs/node-badge/frag.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/node-badge/index.js +33 -0
- package/dist/cjs/packages/graph/src/programs/node-badge/texture.js +455 -0
- package/dist/cjs/packages/graph/src/programs/node-badge/vert.glsl.js +19 -0
- package/dist/cjs/packages/graph/src/programs/node-circle/base/drawHover.js +70 -0
- package/dist/cjs/packages/graph/src/programs/node-circle/base/drawLabel.js +112 -0
- package/dist/cjs/packages/graph/src/programs/node-circle/base/frag.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/node-circle/base/index.js +136 -0
- package/dist/cjs/packages/graph/src/programs/node-circle/base/vert.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/node-circle/index.js +15 -0
- package/dist/cjs/packages/graph/src/programs/node-image/factory.js +223 -0
- package/dist/cjs/packages/graph/src/programs/node-image/frag.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/node-image/index.js +14 -0
- package/dist/cjs/packages/graph/src/programs/node-image/texture.js +472 -0
- package/dist/cjs/packages/graph/src/programs/node-image/vert.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/node-rect/base/drawHover.js +67 -0
- package/dist/cjs/packages/graph/src/programs/node-rect/base/drawLabel.js +106 -0
- package/dist/cjs/packages/graph/src/programs/node-rect/base/frag.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/node-rect/base/index.js +135 -0
- package/dist/cjs/packages/graph/src/programs/node-rect/base/vert.glsl.js +8 -0
- package/dist/cjs/packages/graph/src/programs/node-rect/index.js +15 -0
- package/dist/esm/_virtual/_commonjs-dynamic-modules.js +7 -0
- package/dist/esm/_virtual/_commonjsHelpers.js +7 -0
- package/dist/esm/_virtual/_rollup-plugin-web-worker-loader__helper__auto__createBase64WorkerFactory.js +14 -0
- package/dist/esm/_virtual/_rollup-plugin-web-worker-loader__helper__auto__isNodeJS.js +9 -0
- package/dist/esm/_virtual/_rollup-plugin-web-worker-loader__helper__browser__createBase64WorkerFactory.js +34 -0
- package/dist/esm/_virtual/_rollup-plugin-web-worker-loader__helper__node__WorkerClass.js +13 -0
- package/dist/esm/_virtual/_rollup-plugin-web-worker-loader__helper__node__createBase64WorkerFactory.js +20 -0
- package/dist/esm/_virtual/elk-worker.js +8 -0
- package/dist/esm/_virtual/elk.bundled.js +5 -0
- package/dist/esm/node_modules/elkjs/lib/elk.bundled.js +6667 -0
- package/dist/esm/packages/graph/src/components/Context.js +107 -0
- package/dist/esm/packages/graph/src/components/ContextMenu.js +134 -0
- package/dist/esm/packages/graph/src/components/Tools.js +127 -0
- package/dist/esm/packages/graph/src/components/Viewer.js +57 -0
- package/dist/esm/packages/graph/src/constants/index.js +16 -0
- package/dist/esm/packages/graph/src/graph/index.js +425 -0
- package/dist/esm/packages/graph/src/hooks/sigmaDragSelect.js +169 -0
- package/dist/esm/packages/graph/src/hooks/sigmaHilighter.js +83 -0
- package/dist/esm/packages/graph/src/hooks/sigmaMouseActions.js +145 -0
- package/dist/esm/packages/graph/src/hooks/useGraphology.js +41 -0
- package/dist/esm/packages/graph/src/hooks/useSigma.js +112 -0
- package/dist/esm/packages/graph/src/index.js +30 -0
- package/dist/esm/packages/graph/src/programs/arrow-head/frag.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/arrow-head/index.js +141 -0
- package/dist/esm/packages/graph/src/programs/arrow-head/vert.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/edge-curve/drawLabel.js +136 -0
- package/dist/esm/packages/graph/src/programs/edge-curve/frag.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/edge-curve/index.js +156 -0
- package/dist/esm/packages/graph/src/programs/edge-curve/vert.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/edge-line/drawLabel.js +70 -0
- package/dist/esm/packages/graph/src/programs/edge-line/frag.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/edge-line/index.js +166 -0
- package/dist/esm/packages/graph/src/programs/edge-line/vert.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/node-badge/factory.js +249 -0
- package/dist/esm/packages/graph/src/programs/node-badge/frag.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/node-badge/index.js +32 -0
- package/dist/esm/packages/graph/src/programs/node-badge/texture.js +445 -0
- package/dist/esm/packages/graph/src/programs/node-badge/vert.glsl.js +19 -0
- package/dist/esm/packages/graph/src/programs/node-circle/base/drawHover.js +70 -0
- package/dist/esm/packages/graph/src/programs/node-circle/base/drawLabel.js +112 -0
- package/dist/esm/packages/graph/src/programs/node-circle/base/frag.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/node-circle/base/index.js +136 -0
- package/dist/esm/packages/graph/src/programs/node-circle/base/vert.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/node-circle/index.js +15 -0
- package/dist/esm/packages/graph/src/programs/node-image/factory.js +223 -0
- package/dist/esm/packages/graph/src/programs/node-image/frag.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/node-image/index.js +13 -0
- package/dist/esm/packages/graph/src/programs/node-image/texture.js +462 -0
- package/dist/esm/packages/graph/src/programs/node-image/vert.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/node-rect/base/drawHover.js +67 -0
- package/dist/esm/packages/graph/src/programs/node-rect/base/drawLabel.js +106 -0
- package/dist/esm/packages/graph/src/programs/node-rect/base/frag.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/node-rect/base/index.js +135 -0
- package/dist/esm/packages/graph/src/programs/node-rect/base/vert.glsl.js +8 -0
- package/dist/esm/packages/graph/src/programs/node-rect/index.js +15 -0
- package/dist/types/components/Context.d.ts +18 -0
- package/dist/types/components/ContextMenu.d.ts +1 -0
- package/dist/types/components/Tools.d.ts +1 -0
- package/dist/types/components/Viewer.d.ts +2 -0
- package/dist/types/constants/index.d.ts +12 -0
- package/dist/types/graph/index.d.ts +30 -0
- package/dist/types/graph/layout.worker.d.ts +1 -0
- package/dist/types/hooks/sigmaDragSelect.d.ts +8 -0
- package/dist/types/hooks/sigmaHilighter.d.ts +3 -0
- package/dist/types/hooks/sigmaMouseActions.d.ts +3 -0
- package/dist/types/hooks/useGraphology.d.ts +6 -0
- package/dist/types/hooks/useSigma.d.ts +8 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/programs/arrow-head/frag.glsl.d.ts +2 -0
- package/dist/types/programs/arrow-head/index.d.ts +9 -0
- package/dist/types/programs/arrow-head/vert.glsl.d.ts +2 -0
- package/dist/types/programs/edge-curve/drawLabel.d.ts +6 -0
- package/dist/types/programs/edge-curve/frag.glsl.d.ts +2 -0
- package/dist/types/programs/edge-curve/index.d.ts +43 -0
- package/dist/types/programs/edge-curve/vert.glsl.d.ts +2 -0
- package/dist/types/programs/edge-line/drawLabel.d.ts +5 -0
- package/dist/types/programs/edge-line/frag.glsl.d.ts +2 -0
- package/dist/types/programs/edge-line/index.d.ts +11 -0
- package/dist/types/programs/edge-line/vert.glsl.d.ts +2 -0
- package/dist/types/programs/node-badge/factory.d.ts +27 -0
- package/dist/types/programs/node-badge/frag.glsl.d.ts +2 -0
- package/dist/types/programs/node-badge/index.d.ts +5 -0
- package/dist/types/programs/node-badge/texture.d.ts +102 -0
- package/dist/types/programs/node-badge/vert.glsl.d.ts +2 -0
- package/dist/types/programs/node-circle/base/drawHover.d.ts +8 -0
- package/dist/types/programs/node-circle/base/drawLabel.d.ts +8 -0
- package/dist/types/programs/node-circle/base/frag.glsl.d.ts +2 -0
- package/dist/types/programs/node-circle/base/index.d.ts +37 -0
- package/dist/types/programs/node-circle/base/vert.glsl.d.ts +2 -0
- package/dist/types/programs/node-circle/index.d.ts +11 -0
- package/dist/types/programs/node-image/factory.d.ts +25 -0
- package/dist/types/programs/node-image/frag.glsl.d.ts +2 -0
- package/dist/types/programs/node-image/index.d.ts +5 -0
- package/dist/types/programs/node-image/texture.d.ts +102 -0
- package/dist/types/programs/node-image/vert.glsl.d.ts +2 -0
- package/dist/types/programs/node-rect/base/drawHover.d.ts +8 -0
- package/dist/types/programs/node-rect/base/drawLabel.d.ts +8 -0
- package/dist/types/programs/node-rect/base/frag.glsl.d.ts +2 -0
- package/dist/types/programs/node-rect/base/index.d.ts +34 -0
- package/dist/types/programs/node-rect/base/vert.glsl.d.ts +2 -0
- package/dist/types/programs/node-rect/index.d.ts +11 -0
- package/dist/types/types/index.d.ts +189 -0
- package/package.json +69 -0
- package/src/components/Context.tsx +135 -0
- package/src/components/ContextMenu.tsx +156 -0
- package/src/components/Tools.tsx +107 -0
- package/src/components/Viewer.tsx +75 -0
- package/src/constants/index.ts +22 -0
- package/src/graph/index.ts +428 -0
- package/src/graph/layout.worker.ts +42 -0
- package/src/hooks/sigmaDragSelect.ts +219 -0
- package/src/hooks/sigmaHilighter.ts +107 -0
- package/src/hooks/sigmaMouseActions.ts +153 -0
- package/src/hooks/useGraphology.ts +31 -0
- package/src/hooks/useSigma.ts +118 -0
- package/src/index.ts +34 -0
- package/src/programs/arrow-head/frag.glsl.ts +18 -0
- package/src/programs/arrow-head/index.ts +148 -0
- package/src/programs/arrow-head/vert.glsl.ts +75 -0
- package/src/programs/edge-curve/drawLabel.ts +166 -0
- package/src/programs/edge-curve/frag.glsl.ts +86 -0
- package/src/programs/edge-curve/index.ts +158 -0
- package/src/programs/edge-curve/vert.glsl.ts +110 -0
- package/src/programs/edge-line/drawLabel.ts +113 -0
- package/src/programs/edge-line/frag.glsl.ts +34 -0
- package/src/programs/edge-line/index.ts +165 -0
- package/src/programs/edge-line/vert.glsl.ts +104 -0
- package/src/programs/node-badge/factory.ts +327 -0
- package/src/programs/node-badge/frag.glsl.ts +79 -0
- package/src/programs/node-badge/index.ts +35 -0
- package/src/programs/node-badge/texture.ts +425 -0
- package/src/programs/node-badge/vert.glsl.ts +99 -0
- package/src/programs/node-circle/base/drawHover.ts +80 -0
- package/src/programs/node-circle/base/drawLabel.ts +145 -0
- package/src/programs/node-circle/base/frag.glsl.ts +72 -0
- package/src/programs/node-circle/base/index.ts +102 -0
- package/src/programs/node-circle/base/vert.glsl.ts +83 -0
- package/src/programs/node-circle/index.ts +19 -0
- package/src/programs/node-image/factory.ts +301 -0
- package/src/programs/node-image/frag.glsl.ts +97 -0
- package/src/programs/node-image/index.ts +7 -0
- package/src/programs/node-image/texture.ts +435 -0
- package/src/programs/node-image/vert.glsl.ts +60 -0
- package/src/programs/node-rect/base/drawHover.ts +77 -0
- package/src/programs/node-rect/base/drawLabel.ts +149 -0
- package/src/programs/node-rect/base/frag.glsl.ts +67 -0
- package/src/programs/node-rect/base/index.ts +109 -0
- package/src/programs/node-rect/base/vert.glsl.ts +87 -0
- package/src/programs/node-rect/index.ts +19 -0
- package/src/types/index.ts +210 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { type CreateEdgeCurveProgramOptions } from "@sigma/edge-curve/dist/declarations/src/utils";
|
|
2
|
+
import { type Attributes } from "graphology-types";
|
|
3
|
+
import { type EdgeLabelDrawingFunction } from "sigma/rendering";
|
|
4
|
+
import { type Settings } from "sigma/settings";
|
|
5
|
+
|
|
6
|
+
/* istanbul ignore file */
|
|
7
|
+
|
|
8
|
+
interface Point {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function getCurvePoint(t: number, p0: Point, p1: Point, p2: Point): Point {
|
|
14
|
+
const x = (1 - t) ** 2 * p0.x + 2 * (1 - t) * t * p1.x + t ** 2 * p2.x;
|
|
15
|
+
const y = (1 - t) ** 2 * p0.y + 2 * (1 - t) * t * p1.y + t ** 2 * p2.y;
|
|
16
|
+
return { x, y };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function getCurveLength(p0: Point, p1: Point, p2: Point): number {
|
|
20
|
+
const steps = 20;
|
|
21
|
+
let length = 0;
|
|
22
|
+
let lastPoint = p0;
|
|
23
|
+
for (let i = 0; i < steps; i++) {
|
|
24
|
+
const point = getCurvePoint((i + 1) / steps, p0, p1, p2);
|
|
25
|
+
length += Math.sqrt(
|
|
26
|
+
(lastPoint.x - point.x) ** 2 + (lastPoint.y - point.y) ** 2,
|
|
27
|
+
);
|
|
28
|
+
lastPoint = point;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return length;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function createDrawCurvedEdgeLabel<
|
|
35
|
+
N extends Attributes = Attributes,
|
|
36
|
+
E extends Attributes = Attributes,
|
|
37
|
+
G extends Attributes = Attributes,
|
|
38
|
+
>({
|
|
39
|
+
curvatureAttribute,
|
|
40
|
+
defaultCurvature,
|
|
41
|
+
keepLabelUpright = true,
|
|
42
|
+
}: CreateEdgeCurveProgramOptions & {
|
|
43
|
+
keepLabelUpright?: boolean;
|
|
44
|
+
}): EdgeLabelDrawingFunction<N, E, G> {
|
|
45
|
+
return (
|
|
46
|
+
context,
|
|
47
|
+
edgeData,
|
|
48
|
+
sourceData,
|
|
49
|
+
targetData,
|
|
50
|
+
settings: Settings<N, E, G>,
|
|
51
|
+
): void => {
|
|
52
|
+
const size = settings.edgeLabelSize;
|
|
53
|
+
const curvature = edgeData[curvatureAttribute] || defaultCurvature;
|
|
54
|
+
const font = settings.edgeLabelFont;
|
|
55
|
+
const weight = settings.edgeLabelWeight;
|
|
56
|
+
let color = edgeData.color ?? settings.defaultEdgeColor;
|
|
57
|
+
|
|
58
|
+
if (edgeData.selected) color = "#f00";
|
|
59
|
+
if (edgeData.highlight) color = "#F54A4A";
|
|
60
|
+
|
|
61
|
+
let label = edgeData.label;
|
|
62
|
+
|
|
63
|
+
if (!label || edgeData.opacity < 1) return;
|
|
64
|
+
|
|
65
|
+
context.font = `${weight} ${size}px ${font}`;
|
|
66
|
+
|
|
67
|
+
// Computing positions without considering nodes sizes:
|
|
68
|
+
const ltr = !keepLabelUpright || sourceData.x < targetData.x;
|
|
69
|
+
let sourceX = ltr ? sourceData.x : targetData.x;
|
|
70
|
+
let sourceY = ltr ? sourceData.y : targetData.y;
|
|
71
|
+
let targetX = ltr ? targetData.x : sourceData.x;
|
|
72
|
+
let targetY = ltr ? targetData.y : sourceData.y;
|
|
73
|
+
const centerX = (sourceX + targetX) / 2;
|
|
74
|
+
const centerY = (sourceY + targetY) / 2;
|
|
75
|
+
const diffX = targetX - sourceX;
|
|
76
|
+
const diffY = targetY - sourceY;
|
|
77
|
+
const diff = Math.sqrt(diffX ** 2 + diffY ** 2);
|
|
78
|
+
// Anchor point:
|
|
79
|
+
const orientation = ltr ? 1 : -1;
|
|
80
|
+
let anchorX = centerX + diffY * curvature * orientation;
|
|
81
|
+
let anchorY = centerY - diffX * curvature * orientation;
|
|
82
|
+
|
|
83
|
+
// Adapt curve points to edge thickness:
|
|
84
|
+
const offset = edgeData.size * 0.7 + 5;
|
|
85
|
+
const sourceOffsetVector = {
|
|
86
|
+
x: anchorY - sourceY,
|
|
87
|
+
y: -(anchorX - sourceX),
|
|
88
|
+
};
|
|
89
|
+
const sourceOffsetVectorLength = Math.sqrt(
|
|
90
|
+
sourceOffsetVector.x ** 2 + sourceOffsetVector.y ** 2,
|
|
91
|
+
);
|
|
92
|
+
const targetOffsetVector = {
|
|
93
|
+
x: targetY - anchorY,
|
|
94
|
+
y: -(targetX - anchorX),
|
|
95
|
+
};
|
|
96
|
+
const targetOffsetVectorLength = Math.sqrt(
|
|
97
|
+
targetOffsetVector.x ** 2 + targetOffsetVector.y ** 2,
|
|
98
|
+
);
|
|
99
|
+
sourceX += (offset * sourceOffsetVector.x) / sourceOffsetVectorLength;
|
|
100
|
+
sourceY += (offset * sourceOffsetVector.y) / sourceOffsetVectorLength;
|
|
101
|
+
targetX += (offset * targetOffsetVector.x) / targetOffsetVectorLength;
|
|
102
|
+
targetY += (offset * targetOffsetVector.y) / targetOffsetVectorLength;
|
|
103
|
+
// For anchor, the vector is simpler, so it is inlined:
|
|
104
|
+
anchorX += (offset * diffY) / diff;
|
|
105
|
+
anchorY -= (offset * diffX) / diff;
|
|
106
|
+
|
|
107
|
+
// Compute curve length:
|
|
108
|
+
const anchorPoint = { x: anchorX, y: anchorY };
|
|
109
|
+
const sourcePoint = { x: sourceX, y: sourceY };
|
|
110
|
+
const targetPoint = { x: targetX, y: targetY };
|
|
111
|
+
const curveLength = getCurveLength(sourcePoint, anchorPoint, targetPoint);
|
|
112
|
+
|
|
113
|
+
if (curveLength < sourceData.size + targetData.size) return;
|
|
114
|
+
|
|
115
|
+
// Handling ellipsis
|
|
116
|
+
let textLength = context.measureText(label).width;
|
|
117
|
+
const availableTextLength = curveLength - sourceData.size - targetData.size;
|
|
118
|
+
if (textLength > availableTextLength) {
|
|
119
|
+
const ellipsis = "…";
|
|
120
|
+
label = label + ellipsis;
|
|
121
|
+
textLength = context.measureText(label).width;
|
|
122
|
+
|
|
123
|
+
while (textLength > availableTextLength && label.length > 1) {
|
|
124
|
+
label = label.slice(0, -2) + ellipsis;
|
|
125
|
+
textLength = context.measureText(label).width;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (label.length < 4) return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Measure each character:
|
|
132
|
+
const charactersLengthCache: Record<string, number> = {};
|
|
133
|
+
for (let i = 0, length = label.length; i < length; i++) {
|
|
134
|
+
const character = label[i];
|
|
135
|
+
|
|
136
|
+
if (!charactersLengthCache[character]) {
|
|
137
|
+
charactersLengthCache[character] =
|
|
138
|
+
context.measureText(character).width * (1 + curvature * 0.35);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Draw each character:
|
|
143
|
+
let t = 0.5 - textLength / curveLength / 2;
|
|
144
|
+
for (let i = 0, length = label.length; i < length; i++) {
|
|
145
|
+
const character = label[i];
|
|
146
|
+
const point = getCurvePoint(t, sourcePoint, anchorPoint, targetPoint);
|
|
147
|
+
|
|
148
|
+
const tangentX =
|
|
149
|
+
2 * (1 - t) * (anchorX - sourceX) + 2 * t * (targetX - anchorX);
|
|
150
|
+
const tangentY =
|
|
151
|
+
2 * (1 - t) * (anchorY - sourceY) + 2 * t * (targetY - anchorY);
|
|
152
|
+
const angle = Math.atan2(tangentY, tangentX);
|
|
153
|
+
|
|
154
|
+
context.save();
|
|
155
|
+
context.translate(point.x, point.y);
|
|
156
|
+
context.rotate(angle);
|
|
157
|
+
|
|
158
|
+
context.fillStyle = color;
|
|
159
|
+
context.fillText(character, 0, 0);
|
|
160
|
+
|
|
161
|
+
context.restore();
|
|
162
|
+
|
|
163
|
+
t += charactersLengthCache[character] / curveLength;
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* istanbul ignore file */
|
|
2
|
+
|
|
3
|
+
// language=GLSL
|
|
4
|
+
const SHADER = /* glsl */ `
|
|
5
|
+
precision highp float;
|
|
6
|
+
|
|
7
|
+
varying vec4 v_color;
|
|
8
|
+
varying float v_opacity;
|
|
9
|
+
varying float v_thickness;
|
|
10
|
+
varying float v_feather;
|
|
11
|
+
varying vec2 v_cpA;
|
|
12
|
+
varying vec2 v_cpB;
|
|
13
|
+
varying vec2 v_cpC;
|
|
14
|
+
varying float v_sourceSize;
|
|
15
|
+
varying vec2 v_sourcePoint;
|
|
16
|
+
varying float v_targetSize;
|
|
17
|
+
varying vec2 v_targetPoint;
|
|
18
|
+
|
|
19
|
+
uniform float u_lengthToThicknessRatio;
|
|
20
|
+
uniform float u_widenessToThicknessRatio;
|
|
21
|
+
|
|
22
|
+
float det(vec2 a, vec2 b) {
|
|
23
|
+
return a.x * b.y - b.x * a.y;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
vec2 getDistanceVector(vec2 b0, vec2 b1, vec2 b2) {
|
|
27
|
+
float a = det(b0, b2), b = 2.0 * det(b1, b0), d = 2.0 * det(b2, b1);
|
|
28
|
+
float f = b * d - a * a;
|
|
29
|
+
vec2 d21 = b2 - b1, d10 = b1 - b0, d20 = b2 - b0;
|
|
30
|
+
vec2 gf = 2.0 * (b * d21 + d * d10 + a * d20);
|
|
31
|
+
gf = vec2(gf.y, -gf.x);
|
|
32
|
+
vec2 pp = -f * gf / dot(gf, gf);
|
|
33
|
+
vec2 d0p = b0 - pp;
|
|
34
|
+
float ap = det(d0p, d20), bp = 2.0 * det(d10, d0p);
|
|
35
|
+
float t = clamp((ap + bp) / (2.0 * a + b + d), 0.0, 1.0);
|
|
36
|
+
return mix(mix(b0, b1, t), mix(b1, b2, t), t);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
float distToQuadraticBezierCurve(vec2 p, vec2 b0, vec2 b1, vec2 b2) {
|
|
40
|
+
return length(getDistanceVector(b0 - p, b1 - p, b2 - p));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const float epsilon = 0.7;
|
|
44
|
+
const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);
|
|
45
|
+
|
|
46
|
+
void main(void) {
|
|
47
|
+
float dist = distToQuadraticBezierCurve(gl_FragCoord.xy, v_cpA, v_cpB, v_cpC);
|
|
48
|
+
float thickness = v_thickness;
|
|
49
|
+
|
|
50
|
+
if(v_sourceSize > 0.0) {
|
|
51
|
+
float distToSource = length(gl_FragCoord.xy - v_sourcePoint);
|
|
52
|
+
float sourceArrowLength = v_sourceSize + (thickness) * u_lengthToThicknessRatio;
|
|
53
|
+
if (distToSource < sourceArrowLength) {
|
|
54
|
+
thickness = (distToSource - v_sourceSize) / (sourceArrowLength - v_sourceSize) * u_widenessToThicknessRatio * thickness;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if(v_targetSize > 0.0) {
|
|
59
|
+
float distToTarget = length(gl_FragCoord.xy - v_targetPoint);
|
|
60
|
+
float targetArrowLength = v_targetSize + (thickness) * u_lengthToThicknessRatio;
|
|
61
|
+
if (distToTarget < targetArrowLength) {
|
|
62
|
+
thickness = (distToTarget - v_targetSize) / (targetArrowLength - v_targetSize) * u_widenessToThicknessRatio * thickness;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
float halfThickness = thickness / 2.0;
|
|
67
|
+
if (dist < halfThickness) {
|
|
68
|
+
#ifdef PICKING_MODE
|
|
69
|
+
gl_FragColor = v_color;
|
|
70
|
+
#else
|
|
71
|
+
float t = smoothstep(
|
|
72
|
+
halfThickness - v_feather,
|
|
73
|
+
halfThickness,
|
|
74
|
+
dist
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
gl_FragColor = mix(v_color, transparent, t);
|
|
78
|
+
gl_FragColor = mix(transparent, gl_FragColor, v_opacity);
|
|
79
|
+
#endif
|
|
80
|
+
} else {
|
|
81
|
+
gl_FragColor = transparent;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
`;
|
|
85
|
+
|
|
86
|
+
export default SHADER;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/naming-convention */
|
|
2
|
+
|
|
3
|
+
import { DEFAULT_EDGE_CURVATURE } from "@sigma/edge-curve";
|
|
4
|
+
import { type Attributes } from "graphology-types";
|
|
5
|
+
import {
|
|
6
|
+
createEdgeCompoundProgram,
|
|
7
|
+
EdgeProgram,
|
|
8
|
+
type ProgramInfo,
|
|
9
|
+
} from "sigma/rendering";
|
|
10
|
+
import {
|
|
11
|
+
type EdgeDisplayData,
|
|
12
|
+
type NodeDisplayData,
|
|
13
|
+
type RenderParams,
|
|
14
|
+
} from "sigma/types";
|
|
15
|
+
import { floatColor } from "sigma/utils";
|
|
16
|
+
import { InternalEdgeAttributes } from "../../types";
|
|
17
|
+
import { createDrawCurvedEdgeLabel } from "./drawLabel";
|
|
18
|
+
import FRAGMENT_SHADER_SOURCE from "./frag.glsl";
|
|
19
|
+
import VERTEX_SHADER_SOURCE from "./vert.glsl";
|
|
20
|
+
|
|
21
|
+
/* istanbul ignore file */
|
|
22
|
+
|
|
23
|
+
const { UNSIGNED_BYTE, FLOAT } = WebGLRenderingContext;
|
|
24
|
+
|
|
25
|
+
const UNIFORMS = [
|
|
26
|
+
"u_matrix",
|
|
27
|
+
"u_sizeRatio",
|
|
28
|
+
"u_dimensions",
|
|
29
|
+
"u_pixelRatio",
|
|
30
|
+
"u_feather",
|
|
31
|
+
"u_minEdgeThickness",
|
|
32
|
+
"u_lengthToThicknessRatio",
|
|
33
|
+
"u_widenessToThicknessRatio",
|
|
34
|
+
] as const;
|
|
35
|
+
|
|
36
|
+
export class EdgeCurveProgramBase<
|
|
37
|
+
N extends Attributes = Attributes,
|
|
38
|
+
E extends Attributes = Attributes,
|
|
39
|
+
G extends Attributes = Attributes,
|
|
40
|
+
> extends EdgeProgram<(typeof UNIFORMS)[number], N, E, G> {
|
|
41
|
+
getDefinition() {
|
|
42
|
+
return {
|
|
43
|
+
VERTICES: 6,
|
|
44
|
+
VERTEX_SHADER_SOURCE,
|
|
45
|
+
FRAGMENT_SHADER_SOURCE,
|
|
46
|
+
METHOD: WebGLRenderingContext.TRIANGLES,
|
|
47
|
+
UNIFORMS,
|
|
48
|
+
ATTRIBUTES: [
|
|
49
|
+
{ name: "a_source", size: 2, type: FLOAT },
|
|
50
|
+
{ name: "a_target", size: 2, type: FLOAT },
|
|
51
|
+
{ name: "a_thickness", size: 1, type: FLOAT },
|
|
52
|
+
{ name: "a_curvature", size: 1, type: FLOAT },
|
|
53
|
+
{ name: "a_color", size: 4, type: UNSIGNED_BYTE, normalized: true },
|
|
54
|
+
{ name: "a_opacity", size: 1, type: FLOAT },
|
|
55
|
+
{ name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true },
|
|
56
|
+
{ name: "a_sourceSize", size: 1, type: FLOAT },
|
|
57
|
+
{ name: "a_targetSize", size: 1, type: FLOAT },
|
|
58
|
+
],
|
|
59
|
+
CONSTANT_ATTRIBUTES: [
|
|
60
|
+
{ name: "a_current", size: 1, type: FLOAT }, // TODO: could optimize to bool
|
|
61
|
+
{ name: "a_direction", size: 1, type: FLOAT }, // TODO: could optimize to byte
|
|
62
|
+
],
|
|
63
|
+
CONSTANT_DATA: [
|
|
64
|
+
[0, 1],
|
|
65
|
+
[0, -1],
|
|
66
|
+
[1, 1],
|
|
67
|
+
[0, -1],
|
|
68
|
+
[1, 1],
|
|
69
|
+
[1, -1],
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
processVisibleItem(
|
|
75
|
+
edgeIndex: number,
|
|
76
|
+
startIndex: number,
|
|
77
|
+
sourceData: NodeDisplayData,
|
|
78
|
+
targetData: NodeDisplayData,
|
|
79
|
+
data: EdgeDisplayData & InternalEdgeAttributes,
|
|
80
|
+
) {
|
|
81
|
+
let color = data.color ?? this.renderer.getSetting("defaultEdgeColor");
|
|
82
|
+
if (data.selected) color = "#f00";
|
|
83
|
+
if (data.highlight) color = "#F54A4A";
|
|
84
|
+
|
|
85
|
+
const thickness =
|
|
86
|
+
Math.min(data.size || 1, 0.5) *
|
|
87
|
+
(data.selected || data.highlight ? 16 : 8);
|
|
88
|
+
const x1 = sourceData.x;
|
|
89
|
+
const y1 = sourceData.y;
|
|
90
|
+
const x2 = targetData.x;
|
|
91
|
+
const y2 = targetData.y;
|
|
92
|
+
const curvature = data.curvature ?? DEFAULT_EDGE_CURVATURE;
|
|
93
|
+
|
|
94
|
+
const sourceRadius = sourceData.size || 1;
|
|
95
|
+
const targetRadius = targetData.size || 1;
|
|
96
|
+
|
|
97
|
+
const array = this.array;
|
|
98
|
+
|
|
99
|
+
// First point
|
|
100
|
+
array[startIndex++] = x1;
|
|
101
|
+
array[startIndex++] = y1;
|
|
102
|
+
array[startIndex++] = x2;
|
|
103
|
+
array[startIndex++] = y2;
|
|
104
|
+
array[startIndex++] = thickness;
|
|
105
|
+
array[startIndex++] = curvature;
|
|
106
|
+
array[startIndex++] = floatColor(color);
|
|
107
|
+
array[startIndex++] = data.opacity ?? 1;
|
|
108
|
+
array[startIndex++] = edgeIndex;
|
|
109
|
+
array[startIndex++] = ["both", "source"].includes(data.arrow ?? "")
|
|
110
|
+
? sourceRadius
|
|
111
|
+
: 0;
|
|
112
|
+
array[startIndex++] = ["both", "target"].includes(data.arrow ?? "")
|
|
113
|
+
? targetRadius
|
|
114
|
+
: 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
setUniforms(
|
|
118
|
+
params: RenderParams,
|
|
119
|
+
{ gl, uniformLocations }: ProgramInfo,
|
|
120
|
+
): void {
|
|
121
|
+
const {
|
|
122
|
+
u_matrix,
|
|
123
|
+
u_pixelRatio,
|
|
124
|
+
u_feather,
|
|
125
|
+
u_sizeRatio,
|
|
126
|
+
u_dimensions,
|
|
127
|
+
u_minEdgeThickness,
|
|
128
|
+
u_lengthToThicknessRatio,
|
|
129
|
+
u_widenessToThicknessRatio,
|
|
130
|
+
} = uniformLocations;
|
|
131
|
+
|
|
132
|
+
gl.uniformMatrix3fv(u_matrix, false, params.matrix);
|
|
133
|
+
gl.uniform1f(u_pixelRatio, params.pixelRatio);
|
|
134
|
+
gl.uniform1f(u_sizeRatio, params.sizeRatio);
|
|
135
|
+
gl.uniform1f(u_feather, params.antiAliasingFeather);
|
|
136
|
+
gl.uniform2f(
|
|
137
|
+
u_dimensions,
|
|
138
|
+
params.width * params.pixelRatio,
|
|
139
|
+
params.height * params.pixelRatio,
|
|
140
|
+
);
|
|
141
|
+
gl.uniform1f(u_minEdgeThickness, params.minEdgeThickness);
|
|
142
|
+
gl.uniform1f(u_lengthToThicknessRatio, 2.5);
|
|
143
|
+
gl.uniform1f(u_widenessToThicknessRatio, 2);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const EdgeCurveProgram = createEdgeCompoundProgram(
|
|
148
|
+
[
|
|
149
|
+
EdgeCurveProgramBase,
|
|
150
|
+
// createEdgeArrowHeadProgram({ extremity: "source" }),
|
|
151
|
+
// createEdgeArrowHeadProgram({ extremity: "target" }),
|
|
152
|
+
],
|
|
153
|
+
createDrawCurvedEdgeLabel({
|
|
154
|
+
curvatureAttribute: "curvature",
|
|
155
|
+
defaultCurvature: DEFAULT_EDGE_CURVATURE,
|
|
156
|
+
arrowHead: null,
|
|
157
|
+
}) as any,
|
|
158
|
+
);
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/* istanbul ignore file */
|
|
2
|
+
|
|
3
|
+
// language=GLSL
|
|
4
|
+
const SHADER = /* glsl */ `
|
|
5
|
+
attribute vec4 a_id;
|
|
6
|
+
attribute vec4 a_color;
|
|
7
|
+
attribute float a_direction;
|
|
8
|
+
attribute float a_thickness;
|
|
9
|
+
attribute float a_opacity;
|
|
10
|
+
attribute vec2 a_source;
|
|
11
|
+
attribute vec2 a_target;
|
|
12
|
+
attribute float a_current;
|
|
13
|
+
attribute float a_curvature;
|
|
14
|
+
attribute float a_sourceSize;
|
|
15
|
+
attribute float a_targetSize;
|
|
16
|
+
|
|
17
|
+
uniform mat3 u_matrix;
|
|
18
|
+
uniform float u_sizeRatio;
|
|
19
|
+
uniform float u_pixelRatio;
|
|
20
|
+
uniform vec2 u_dimensions;
|
|
21
|
+
uniform float u_minEdgeThickness;
|
|
22
|
+
uniform float u_feather;
|
|
23
|
+
uniform float u_widenessToThicknessRatio;
|
|
24
|
+
|
|
25
|
+
varying vec4 v_color;
|
|
26
|
+
varying float v_opacity;
|
|
27
|
+
varying float v_thickness;
|
|
28
|
+
varying float v_feather;
|
|
29
|
+
varying vec2 v_cpA;
|
|
30
|
+
varying vec2 v_cpB;
|
|
31
|
+
varying vec2 v_cpC;
|
|
32
|
+
varying float v_sourceSize;
|
|
33
|
+
varying vec2 v_sourcePoint;
|
|
34
|
+
varying float v_targetSize;
|
|
35
|
+
varying vec2 v_targetPoint;
|
|
36
|
+
|
|
37
|
+
const float bias = 255.0 / 254.0;
|
|
38
|
+
const float epsilon = 0.7;
|
|
39
|
+
|
|
40
|
+
vec2 clipspaceToViewport(vec2 pos, vec2 dimensions) {
|
|
41
|
+
return vec2(
|
|
42
|
+
(pos.x + 1.0) * dimensions.x / 2.0,
|
|
43
|
+
(pos.y + 1.0) * dimensions.y / 2.0
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
vec2 viewportToClipspace(vec2 pos, vec2 dimensions) {
|
|
48
|
+
return vec2(
|
|
49
|
+
pos.x / dimensions.x * 2.0 - 1.0,
|
|
50
|
+
pos.y / dimensions.y * 2.0 - 1.0
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
void main() {
|
|
55
|
+
float minThickness = u_minEdgeThickness;
|
|
56
|
+
// Selecting the correct position
|
|
57
|
+
// Branchless "position = a_source if a_current == 1.0 else a_target"
|
|
58
|
+
vec2 position = a_source * max(0.0, a_current) + a_target * max(0.0, 1.0 - a_current);
|
|
59
|
+
position = (u_matrix * vec3(position, 1)).xy;
|
|
60
|
+
|
|
61
|
+
vec2 source = (u_matrix * vec3(a_source, 1)).xy;
|
|
62
|
+
vec2 target = (u_matrix * vec3(a_target, 1)).xy;
|
|
63
|
+
|
|
64
|
+
vec2 viewportPosition = clipspaceToViewport(position, u_dimensions);
|
|
65
|
+
vec2 viewportSource = clipspaceToViewport(source, u_dimensions);
|
|
66
|
+
vec2 viewportTarget = clipspaceToViewport(target, u_dimensions);
|
|
67
|
+
|
|
68
|
+
vec2 delta = viewportTarget.xy - viewportSource.xy;
|
|
69
|
+
float len = length(delta);
|
|
70
|
+
vec2 normal = vec2(-delta.y, delta.x) * a_direction;
|
|
71
|
+
vec2 unitNormal = normal / len;
|
|
72
|
+
float boundingBoxThickness = len * a_curvature;
|
|
73
|
+
float curveThickness = max(minThickness, a_thickness / 2.0 / u_sizeRatio * u_pixelRatio);
|
|
74
|
+
|
|
75
|
+
v_thickness = curveThickness;
|
|
76
|
+
v_feather = u_feather;
|
|
77
|
+
|
|
78
|
+
v_cpA = viewportSource;
|
|
79
|
+
v_cpB = 0.5 * (viewportSource + viewportTarget) + unitNormal * a_direction * boundingBoxThickness;
|
|
80
|
+
v_cpC = viewportTarget;
|
|
81
|
+
|
|
82
|
+
vec2 viewportOffsetPosition = (
|
|
83
|
+
viewportPosition +
|
|
84
|
+
unitNormal * (boundingBoxThickness / 2.0 + sign(boundingBoxThickness) * (curveThickness + epsilon)) *
|
|
85
|
+
max(0.0, a_direction) // NOTE: cutting the bounding box in half to avoid overdraw
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
position = viewportToClipspace(viewportOffsetPosition, u_dimensions);
|
|
89
|
+
gl_Position = vec4(position, 0, 1);
|
|
90
|
+
|
|
91
|
+
v_sourceSize = a_sourceSize * u_pixelRatio / u_sizeRatio;
|
|
92
|
+
v_sourcePoint = viewportSource;
|
|
93
|
+
|
|
94
|
+
v_targetSize = a_targetSize * u_pixelRatio / u_sizeRatio;
|
|
95
|
+
v_targetPoint = viewportTarget;
|
|
96
|
+
|
|
97
|
+
#ifdef PICKING_MODE
|
|
98
|
+
// For picking mode, we use the ID as the color:
|
|
99
|
+
v_color = a_id;
|
|
100
|
+
#else
|
|
101
|
+
// For normal mode, we use the color:
|
|
102
|
+
v_color = a_color;
|
|
103
|
+
v_opacity = a_opacity;
|
|
104
|
+
#endif
|
|
105
|
+
|
|
106
|
+
v_color.a *= bias;
|
|
107
|
+
}
|
|
108
|
+
`;
|
|
109
|
+
|
|
110
|
+
export default SHADER;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { type Attributes } from "graphology-types";
|
|
2
|
+
import { type Settings } from "sigma/settings";
|
|
3
|
+
import {
|
|
4
|
+
type EdgeDisplayData,
|
|
5
|
+
type NodeDisplayData,
|
|
6
|
+
type PartialButFor,
|
|
7
|
+
} from "sigma/types";
|
|
8
|
+
|
|
9
|
+
/* istanbul ignore file */
|
|
10
|
+
|
|
11
|
+
export type EdgeLabelDrawingFunction<
|
|
12
|
+
N extends Attributes = Attributes,
|
|
13
|
+
E extends Attributes = Attributes,
|
|
14
|
+
G extends Attributes = Attributes,
|
|
15
|
+
> = (
|
|
16
|
+
context: CanvasRenderingContext2D,
|
|
17
|
+
edgeData: PartialButFor<EdgeDisplayData, "label" | "color" | "size">,
|
|
18
|
+
sourceData: PartialButFor<NodeDisplayData, "x" | "y" | "size">,
|
|
19
|
+
targetData: PartialButFor<NodeDisplayData, "x" | "y" | "size">,
|
|
20
|
+
settings: Settings<N, E, G>,
|
|
21
|
+
) => void;
|
|
22
|
+
|
|
23
|
+
export function drawLineLabel<
|
|
24
|
+
N extends Attributes = Attributes,
|
|
25
|
+
E extends Attributes = Attributes,
|
|
26
|
+
G extends Attributes = Attributes,
|
|
27
|
+
>(
|
|
28
|
+
context: CanvasRenderingContext2D,
|
|
29
|
+
edgeData: PartialButFor<EdgeDisplayData, "label" | "color" | "size">,
|
|
30
|
+
sourceData: PartialButFor<NodeDisplayData, "x" | "y" | "size">,
|
|
31
|
+
targetData: PartialButFor<NodeDisplayData, "x" | "y" | "size">,
|
|
32
|
+
settings: Settings<N, E, G>,
|
|
33
|
+
): void {
|
|
34
|
+
const size = settings.edgeLabelSize;
|
|
35
|
+
const font = settings.edgeLabelFont;
|
|
36
|
+
const weight = settings.edgeLabelWeight;
|
|
37
|
+
let color = edgeData.color ?? settings.defaultEdgeColor;
|
|
38
|
+
|
|
39
|
+
if (edgeData.selected) color = "#f00";
|
|
40
|
+
if (edgeData.highlight) color = "#F54A4A";
|
|
41
|
+
|
|
42
|
+
let label = edgeData.label;
|
|
43
|
+
|
|
44
|
+
if (!label || edgeData.opacity < 1) return;
|
|
45
|
+
|
|
46
|
+
context.font = `${weight} ${size}px ${font}`;
|
|
47
|
+
|
|
48
|
+
// Computing positions without considering nodes sizes:
|
|
49
|
+
const sSize = sourceData.size;
|
|
50
|
+
const tSize = targetData.size;
|
|
51
|
+
let sx = sourceData.x;
|
|
52
|
+
let sy = sourceData.y;
|
|
53
|
+
let tx = targetData.x;
|
|
54
|
+
let ty = targetData.y;
|
|
55
|
+
let cx = (sx + tx) / 2;
|
|
56
|
+
let cy = (sy + ty) / 2;
|
|
57
|
+
let dx = tx - sx;
|
|
58
|
+
let dy = ty - sy;
|
|
59
|
+
let d = Math.sqrt(dx * dx + dy * dy);
|
|
60
|
+
|
|
61
|
+
if (d < sSize + tSize) return;
|
|
62
|
+
|
|
63
|
+
// Adding nodes sizes:
|
|
64
|
+
sx += (dx * sSize) / d;
|
|
65
|
+
sy += (dy * sSize) / d;
|
|
66
|
+
tx -= (dx * tSize) / d;
|
|
67
|
+
ty -= (dy * tSize) / d;
|
|
68
|
+
cx = (sx + tx) / 2;
|
|
69
|
+
cy = (sy + ty) / 2;
|
|
70
|
+
dx = tx - sx;
|
|
71
|
+
dy = ty - sy;
|
|
72
|
+
d = Math.sqrt(dx * dx + dy * dy);
|
|
73
|
+
|
|
74
|
+
// Handling ellipsis
|
|
75
|
+
let textLength = context.measureText(label).width;
|
|
76
|
+
|
|
77
|
+
if (textLength > d) {
|
|
78
|
+
const ellipsis = "…";
|
|
79
|
+
label = label + ellipsis;
|
|
80
|
+
textLength = context.measureText(label).width;
|
|
81
|
+
|
|
82
|
+
while (textLength > d && label.length > 1) {
|
|
83
|
+
label = label.slice(0, -2) + ellipsis;
|
|
84
|
+
textLength = context.measureText(label).width;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (label.length < 4) return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let angle;
|
|
91
|
+
if (dx > 0) {
|
|
92
|
+
if (dy > 0) angle = Math.acos(dx / d);
|
|
93
|
+
else angle = Math.asin(dy / d);
|
|
94
|
+
} else {
|
|
95
|
+
if (dy > 0) angle = Math.acos(dx / d) + Math.PI;
|
|
96
|
+
else angle = Math.asin(dx / d) + Math.PI / 2;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
context.save();
|
|
100
|
+
context.translate(cx, cy);
|
|
101
|
+
context.rotate(angle);
|
|
102
|
+
context.fillStyle = settings.defaultNodeColor || "#fff";
|
|
103
|
+
context.fillRect(
|
|
104
|
+
-textLength / 2 - 4,
|
|
105
|
+
edgeData.size - size + 2,
|
|
106
|
+
textLength + 8,
|
|
107
|
+
size + 2,
|
|
108
|
+
);
|
|
109
|
+
context.fillStyle = color;
|
|
110
|
+
context.fillText(label, -textLength / 2, edgeData.size);
|
|
111
|
+
|
|
112
|
+
context.restore();
|
|
113
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* istanbul ignore file */
|
|
2
|
+
|
|
3
|
+
// language=GLSL
|
|
4
|
+
const SHADER_SOURCE = /* glsl */ `
|
|
5
|
+
precision mediump float;
|
|
6
|
+
|
|
7
|
+
varying vec4 v_color;
|
|
8
|
+
varying vec2 v_normal;
|
|
9
|
+
varying float v_opacity;
|
|
10
|
+
varying float v_thickness;
|
|
11
|
+
varying float v_feather;
|
|
12
|
+
|
|
13
|
+
const vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);
|
|
14
|
+
|
|
15
|
+
void main(void) {
|
|
16
|
+
// We only handle antialiasing for normal mode:
|
|
17
|
+
#ifdef PICKING_MODE
|
|
18
|
+
gl_FragColor = v_color;
|
|
19
|
+
#else
|
|
20
|
+
float dist = length(v_normal) * v_thickness;
|
|
21
|
+
|
|
22
|
+
float t = smoothstep(
|
|
23
|
+
v_thickness - v_feather,
|
|
24
|
+
v_thickness,
|
|
25
|
+
dist
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
gl_FragColor = mix(v_color, transparent, t);
|
|
29
|
+
gl_FragColor = mix(transparent, gl_FragColor, v_opacity);
|
|
30
|
+
#endif
|
|
31
|
+
}
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
export default SHADER_SOURCE;
|