@cosmos.gl/graph 2.4.0 → 2.5.0
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/dist/config.d.ts +69 -0
- package/dist/index.d.ts +16 -6
- package/dist/index.js +4328 -4129
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +113 -45
- package/dist/index.min.js.map +1 -1
- package/dist/modules/Lines/index.d.ts +8 -0
- package/dist/modules/Store/index.d.ts +14 -2
- package/dist/modules/core-module.d.ts +1 -0
- package/dist/stories/beginners/link-hovering/data-generator.d.ts +19 -0
- package/dist/stories/beginners/link-hovering/index.d.ts +5 -0
- package/dist/stories/beginners.stories.d.ts +1 -0
- package/dist/variables.d.ts +5 -2
- package/package.json +1 -1
- package/src/config.ts +86 -2
- package/src/index.ts +151 -31
- package/src/modules/Lines/draw-curve-line.frag +12 -1
- package/src/modules/Lines/draw-curve-line.vert +29 -2
- package/src/modules/Lines/hovered-line-index.frag +27 -0
- package/src/modules/Lines/hovered-line-index.vert +8 -0
- package/src/modules/Lines/index.ts +112 -2
- package/src/modules/Store/index.ts +33 -2
- package/src/modules/core-module.ts +1 -0
- package/src/stories/1. welcome.mdx +2 -1
- package/src/stories/2. configuration.mdx +10 -1
- package/src/stories/3. api-reference.mdx +13 -4
- package/src/stories/beginners/basic-set-up/index.ts +20 -10
- package/src/stories/beginners/link-hovering/data-generator.ts +198 -0
- package/src/stories/beginners/link-hovering/index.ts +61 -0
- package/src/stories/beginners/link-hovering/style.css +73 -0
- package/src/stories/beginners/quick-start.ts +2 -1
- package/src/stories/beginners/remove-points/index.ts +28 -30
- package/src/stories/beginners.stories.ts +17 -0
- package/src/stories/clusters/polygon-selection/index.ts +2 -4
- package/src/stories/shapes/image-example/index.ts +7 -8
- package/src/variables.ts +5 -2
|
@@ -4,13 +4,14 @@ attribute vec2 position, pointA, pointB;
|
|
|
4
4
|
attribute vec4 color;
|
|
5
5
|
attribute float width;
|
|
6
6
|
attribute float arrow;
|
|
7
|
+
attribute float linkIndices;
|
|
7
8
|
|
|
8
9
|
uniform sampler2D positionsTexture;
|
|
9
10
|
uniform sampler2D pointGreyoutStatus;
|
|
10
11
|
uniform mat3 transformationMatrix;
|
|
11
12
|
uniform float pointsTextureSize;
|
|
12
13
|
uniform float widthScale;
|
|
13
|
-
uniform float
|
|
14
|
+
uniform float linkArrowsSizeScale;
|
|
14
15
|
uniform float spaceSize;
|
|
15
16
|
uniform vec2 screenSize;
|
|
16
17
|
uniform vec2 linkVisibilityDistanceRange;
|
|
@@ -22,6 +23,11 @@ uniform float curvedLinkControlPointDistance;
|
|
|
22
23
|
uniform float curvedLinkSegments;
|
|
23
24
|
uniform bool scaleLinksOnZoom;
|
|
24
25
|
uniform float maxPointSize;
|
|
26
|
+
// renderMode: 0.0 = normal rendering, 1.0 = index buffer rendering for picking
|
|
27
|
+
uniform float renderMode;
|
|
28
|
+
uniform float hoveredLinkIndex;
|
|
29
|
+
uniform vec4 hoveredLinkColor;
|
|
30
|
+
uniform float hoveredLinkWidthIncrease;
|
|
25
31
|
|
|
26
32
|
varying vec4 rgbaColor;
|
|
27
33
|
varying vec2 pos;
|
|
@@ -29,6 +35,7 @@ varying float arrowLength;
|
|
|
29
35
|
varying float useArrow;
|
|
30
36
|
varying float smoothing;
|
|
31
37
|
varying float arrowWidthFactor;
|
|
38
|
+
varying float linkIndex;
|
|
32
39
|
|
|
33
40
|
float map(float value, float min1, float max1, float min2, float max2) {
|
|
34
41
|
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
|
@@ -73,6 +80,7 @@ float calculateArrowWidth(float arrowWidth) {
|
|
|
73
80
|
|
|
74
81
|
void main() {
|
|
75
82
|
pos = position;
|
|
83
|
+
linkIndex = linkIndices;
|
|
76
84
|
|
|
77
85
|
vec2 pointTexturePosA = (pointA + 0.5) / pointsTextureSize;
|
|
78
86
|
vec2 pointTexturePosB = (pointB + 0.5) / pointsTextureSize;
|
|
@@ -102,7 +110,7 @@ void main() {
|
|
|
102
110
|
float k = 2.0;
|
|
103
111
|
// Arrow width is proportionally larger than the line width
|
|
104
112
|
float arrowWidth = linkWidth * k;
|
|
105
|
-
arrowWidth *=
|
|
113
|
+
arrowWidth *= linkArrowsSizeScale;
|
|
106
114
|
|
|
107
115
|
// Ensure arrow width difference is non-negative to prevent unwanted changes to link width
|
|
108
116
|
float arrowWidthDifference = max(0.0, arrowWidth - linkWidth);
|
|
@@ -124,10 +132,22 @@ void main() {
|
|
|
124
132
|
|
|
125
133
|
// Calculate final link width in pixels with smoothing
|
|
126
134
|
float linkWidthPx = calculateLinkWidth(linkWidth);
|
|
135
|
+
|
|
136
|
+
if (renderMode > 0.0) {
|
|
137
|
+
// Add 5 pixels padding for better hover detection
|
|
138
|
+
linkWidthPx += 5.0 / transformationMatrix[0][0];
|
|
139
|
+
} else {
|
|
140
|
+
// Add pixel increase if this is the hovered link
|
|
141
|
+
if (hoveredLinkIndex == linkIndex) {
|
|
142
|
+
linkWidthPx += hoveredLinkWidthIncrease / transformationMatrix[0][0];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
127
145
|
float smoothingPx = 0.5 / transformationMatrix[0][0];
|
|
128
146
|
smoothing = smoothingPx / linkWidthPx;
|
|
129
147
|
linkWidthPx += smoothingPx;
|
|
130
148
|
|
|
149
|
+
|
|
150
|
+
|
|
131
151
|
// Calculate final color with opacity based on link distance
|
|
132
152
|
vec3 rgbColor = color.rgb;
|
|
133
153
|
// Adjust opacity based on link distance
|
|
@@ -141,6 +161,13 @@ void main() {
|
|
|
141
161
|
// Pass final color to fragment shader
|
|
142
162
|
rgbaColor = vec4(rgbColor, opacity);
|
|
143
163
|
|
|
164
|
+
// Apply hover color if this is the hovered link and hover color is defined
|
|
165
|
+
if (hoveredLinkIndex == linkIndex && hoveredLinkColor.a > -0.5) {
|
|
166
|
+
// Keep existing RGB values but multiply opacity with hover color opacity
|
|
167
|
+
rgbaColor.rgb = hoveredLinkColor.rgb;
|
|
168
|
+
rgbaColor.a *= hoveredLinkColor.a;
|
|
169
|
+
}
|
|
170
|
+
|
|
144
171
|
// Calculate position on the curved path
|
|
145
172
|
float t = position.x;
|
|
146
173
|
float w = curvedWeight;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
precision highp float;
|
|
2
|
+
|
|
3
|
+
uniform sampler2D linkIndexTexture;
|
|
4
|
+
uniform vec2 mousePosition;
|
|
5
|
+
uniform vec2 screenSize;
|
|
6
|
+
|
|
7
|
+
varying vec2 vTexCoord;
|
|
8
|
+
|
|
9
|
+
void main() {
|
|
10
|
+
// Convert mouse position to texture coordinates
|
|
11
|
+
vec2 texCoord = mousePosition / screenSize;
|
|
12
|
+
|
|
13
|
+
// Read the link index from the linkIndexFbo texture at mouse position
|
|
14
|
+
vec4 linkIndexData = texture2D(linkIndexTexture, texCoord);
|
|
15
|
+
|
|
16
|
+
// Extract the link index (stored in the red channel)
|
|
17
|
+
float linkIndex = linkIndexData.r;
|
|
18
|
+
|
|
19
|
+
// Check if there's a valid link at this position (alpha > 0)
|
|
20
|
+
if (linkIndexData.a > 0.0 && linkIndex >= 0.0) {
|
|
21
|
+
// Output the link index
|
|
22
|
+
gl_FragColor = vec4(linkIndex, 0.0, 0.0, 1.0);
|
|
23
|
+
} else {
|
|
24
|
+
// No link at this position, output -1 to indicate no hover
|
|
25
|
+
gl_FragColor = vec4(-1.0, 0.0, 0.0, 0.0);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -2,21 +2,44 @@ import regl from 'regl'
|
|
|
2
2
|
import { CoreModule } from '@/graph/modules/core-module'
|
|
3
3
|
import drawLineFrag from '@/graph/modules/Lines/draw-curve-line.frag'
|
|
4
4
|
import drawLineVert from '@/graph/modules/Lines/draw-curve-line.vert'
|
|
5
|
+
import hoveredLineIndexFrag from '@/graph/modules/Lines/hovered-line-index.frag'
|
|
6
|
+
import hoveredLineIndexVert from '@/graph/modules/Lines/hovered-line-index.vert'
|
|
5
7
|
import { defaultConfigValues } from '@/graph/variables'
|
|
6
8
|
import { getCurveLineGeometry } from '@/graph/modules/Lines/geometry'
|
|
7
9
|
|
|
8
10
|
export class Lines extends CoreModule {
|
|
11
|
+
public linkIndexFbo: regl.Framebuffer2D | undefined
|
|
12
|
+
public hoveredLineIndexFbo: regl.Framebuffer2D | undefined
|
|
9
13
|
private drawCurveCommand: regl.DrawCommand | undefined
|
|
14
|
+
private hoveredLineIndexCommand: regl.DrawCommand | undefined
|
|
10
15
|
private pointsBuffer: regl.Buffer | undefined
|
|
11
16
|
private colorBuffer: regl.Buffer | undefined
|
|
12
17
|
private widthBuffer: regl.Buffer | undefined
|
|
13
18
|
private arrowBuffer: regl.Buffer | undefined
|
|
14
19
|
private curveLineGeometry: number[][] | undefined
|
|
15
20
|
private curveLineBuffer: regl.Buffer | undefined
|
|
21
|
+
private linkIndexBuffer: regl.Buffer | undefined
|
|
22
|
+
private quadBuffer: regl.Buffer | undefined
|
|
16
23
|
|
|
17
24
|
public initPrograms (): void {
|
|
18
25
|
const { reglInstance, config, store } = this
|
|
19
26
|
|
|
27
|
+
this.updateLinkIndexFbo()
|
|
28
|
+
|
|
29
|
+
// Initialize the hovered line index FBO
|
|
30
|
+
if (!this.hoveredLineIndexFbo) {
|
|
31
|
+
this.hoveredLineIndexFbo = reglInstance.framebuffer({
|
|
32
|
+
color: reglInstance.texture({
|
|
33
|
+
width: 1,
|
|
34
|
+
height: 1,
|
|
35
|
+
format: 'rgba',
|
|
36
|
+
type: 'float',
|
|
37
|
+
}),
|
|
38
|
+
depth: false,
|
|
39
|
+
stencil: false,
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
20
43
|
if (!this.drawCurveCommand) {
|
|
21
44
|
this.drawCurveCommand = reglInstance({
|
|
22
45
|
vert: drawLineVert,
|
|
@@ -57,6 +80,12 @@ export class Lines extends CoreModule {
|
|
|
57
80
|
offset: Float32Array.BYTES_PER_ELEMENT * 0,
|
|
58
81
|
stride: Float32Array.BYTES_PER_ELEMENT * 1,
|
|
59
82
|
},
|
|
83
|
+
linkIndices: {
|
|
84
|
+
buffer: () => this.linkIndexBuffer,
|
|
85
|
+
divisor: 1,
|
|
86
|
+
offset: Float32Array.BYTES_PER_ELEMENT * 0,
|
|
87
|
+
stride: Float32Array.BYTES_PER_ELEMENT * 1,
|
|
88
|
+
},
|
|
60
89
|
},
|
|
61
90
|
uniforms: {
|
|
62
91
|
positionsTexture: () => this.points?.currentPositionFbo,
|
|
@@ -64,7 +93,7 @@ export class Lines extends CoreModule {
|
|
|
64
93
|
transformationMatrix: () => store.transform,
|
|
65
94
|
pointsTextureSize: () => store.pointsTextureSize,
|
|
66
95
|
widthScale: () => config.linkWidthScale,
|
|
67
|
-
|
|
96
|
+
linkArrowsSizeScale: () => config.linkArrowsSizeScale,
|
|
68
97
|
spaceSize: () => store.adjustedSpaceSize,
|
|
69
98
|
screenSize: () => store.screenSize,
|
|
70
99
|
linkVisibilityDistanceRange: () => config.linkVisibilityDistanceRange,
|
|
@@ -76,11 +105,24 @@ export class Lines extends CoreModule {
|
|
|
76
105
|
curvedWeight: () => config.curvedLinkWeight,
|
|
77
106
|
curvedLinkControlPointDistance: () => config.curvedLinkControlPointDistance,
|
|
78
107
|
curvedLinkSegments: () => config.curvedLinks ? config.curvedLinkSegments ?? defaultConfigValues.curvedLinkSegments : 1,
|
|
108
|
+
hoveredLinkIndex: () => store.hoveredLinkIndex ?? -1,
|
|
109
|
+
hoveredLinkColor: () => store.hoveredLinkColor,
|
|
110
|
+
hoveredLinkWidthIncrease: () => config.hoveredLinkWidthIncrease,
|
|
111
|
+
renderMode: reglInstance.prop<{ renderMode: number }, 'renderMode'>('renderMode'),
|
|
79
112
|
},
|
|
80
113
|
cull: {
|
|
81
114
|
enable: true,
|
|
82
115
|
face: 'back',
|
|
83
116
|
},
|
|
117
|
+
/**
|
|
118
|
+
* Blending behavior for link index rendering (renderMode: 1.0 - hover detection):
|
|
119
|
+
*
|
|
120
|
+
* When rendering link indices to the framebuffer, we use full opacity (1.0).
|
|
121
|
+
* This means:
|
|
122
|
+
* - The source color completely overwrites the destination
|
|
123
|
+
* - No blending occurs - it's like drawing with a permanent marker
|
|
124
|
+
* - This preserves the exact index values we need for picking/selection
|
|
125
|
+
*/
|
|
84
126
|
blend: {
|
|
85
127
|
enable: true,
|
|
86
128
|
func: {
|
|
@@ -98,11 +140,37 @@ export class Lines extends CoreModule {
|
|
|
98
140
|
enable: false,
|
|
99
141
|
mask: false,
|
|
100
142
|
},
|
|
143
|
+
framebuffer: reglInstance.prop<{ framebuffer: regl.Framebuffer2D }, 'framebuffer'>('framebuffer'),
|
|
101
144
|
count: () => this.curveLineGeometry?.length ?? 0,
|
|
102
145
|
instances: () => this.data.linksNumber ?? 0,
|
|
103
146
|
primitive: 'triangle strip',
|
|
104
147
|
})
|
|
105
148
|
}
|
|
149
|
+
|
|
150
|
+
if (!this.hoveredLineIndexCommand) {
|
|
151
|
+
this.hoveredLineIndexCommand = reglInstance({
|
|
152
|
+
vert: hoveredLineIndexVert,
|
|
153
|
+
frag: hoveredLineIndexFrag,
|
|
154
|
+
attributes: {
|
|
155
|
+
position: {
|
|
156
|
+
buffer: () => this.quadBuffer,
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
uniforms: {
|
|
160
|
+
linkIndexTexture: () => this.linkIndexFbo,
|
|
161
|
+
mousePosition: () => store.screenMousePosition,
|
|
162
|
+
screenSize: () => store.screenSize,
|
|
163
|
+
},
|
|
164
|
+
framebuffer: this.hoveredLineIndexFbo,
|
|
165
|
+
count: 4,
|
|
166
|
+
primitive: 'triangle strip',
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Initialize quad buffer for full-screen rendering
|
|
171
|
+
if (!this.quadBuffer) {
|
|
172
|
+
this.quadBuffer = reglInstance.buffer([-1, -1, 1, -1, -1, 1, 1, 1])
|
|
173
|
+
}
|
|
106
174
|
}
|
|
107
175
|
|
|
108
176
|
public draw (): void {
|
|
@@ -111,7 +179,28 @@ export class Lines extends CoreModule {
|
|
|
111
179
|
if (!this.widthBuffer) this.updateWidth()
|
|
112
180
|
if (!this.arrowBuffer) this.updateArrow()
|
|
113
181
|
if (!this.curveLineGeometry) this.updateCurveLineGeometry()
|
|
114
|
-
|
|
182
|
+
|
|
183
|
+
// Render normal links (renderMode: 0.0 = normal rendering)
|
|
184
|
+
this.drawCurveCommand?.({ framebuffer: null, renderMode: 0.0 })
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
public updateLinkIndexFbo (): void {
|
|
188
|
+
const { reglInstance, store } = this
|
|
189
|
+
|
|
190
|
+
// Only create and update the link index FBO if link hovering is enabled
|
|
191
|
+
if (!this.store.isLinkHoveringEnabled) return
|
|
192
|
+
|
|
193
|
+
if (!this.linkIndexFbo) this.linkIndexFbo = reglInstance.framebuffer()
|
|
194
|
+
this.linkIndexFbo({
|
|
195
|
+
color: reglInstance.texture({
|
|
196
|
+
width: store.screenSize[0],
|
|
197
|
+
height: store.screenSize[1],
|
|
198
|
+
format: 'rgba',
|
|
199
|
+
type: 'float',
|
|
200
|
+
}),
|
|
201
|
+
depth: false,
|
|
202
|
+
stencil: false,
|
|
203
|
+
})
|
|
115
204
|
}
|
|
116
205
|
|
|
117
206
|
public updatePointsBuffer (): void {
|
|
@@ -134,6 +223,13 @@ export class Lines extends CoreModule {
|
|
|
134
223
|
|
|
135
224
|
if (!this.pointsBuffer) this.pointsBuffer = reglInstance.buffer(0)
|
|
136
225
|
this.pointsBuffer(instancePoints)
|
|
226
|
+
|
|
227
|
+
const linkIndices = new Float32Array(data.linksNumber)
|
|
228
|
+
for (let i = 0; i < data.linksNumber; i++) {
|
|
229
|
+
linkIndices[i] = i
|
|
230
|
+
}
|
|
231
|
+
if (!this.linkIndexBuffer) this.linkIndexBuffer = reglInstance.buffer(0)
|
|
232
|
+
this.linkIndexBuffer(linkIndices)
|
|
137
233
|
}
|
|
138
234
|
|
|
139
235
|
public updateColor (): void {
|
|
@@ -160,4 +256,18 @@ export class Lines extends CoreModule {
|
|
|
160
256
|
if (!this.curveLineBuffer) this.curveLineBuffer = reglInstance.buffer(0)
|
|
161
257
|
this.curveLineBuffer(this.curveLineGeometry)
|
|
162
258
|
}
|
|
259
|
+
|
|
260
|
+
public findHoveredLine (): void {
|
|
261
|
+
if (!this.data.linksNumber || !this.store.isLinkHoveringEnabled) return
|
|
262
|
+
if (!this.linkIndexFbo) this.updateLinkIndexFbo()
|
|
263
|
+
this.reglInstance.clear({
|
|
264
|
+
framebuffer: this.linkIndexFbo as regl.Framebuffer2D,
|
|
265
|
+
color: [0, 0, 0, 0],
|
|
266
|
+
})
|
|
267
|
+
// Render to index buffer for picking/hover detection (renderMode: 1.0 = index rendering)
|
|
268
|
+
this.drawCurveCommand?.({ framebuffer: this.linkIndexFbo, renderMode: 1.0 })
|
|
269
|
+
|
|
270
|
+
// Execute the command to read the link index at mouse position
|
|
271
|
+
this.hoveredLineIndexCommand?.()
|
|
272
|
+
}
|
|
163
273
|
}
|
|
@@ -3,10 +3,18 @@ import { mat3 } from 'gl-matrix'
|
|
|
3
3
|
import { Random } from 'random'
|
|
4
4
|
import { getRgbaColor, rgbToBrightness } from '@/graph/helper'
|
|
5
5
|
import { hoveredPointRingOpacity, focusedPointRingOpacity, defaultConfigValues } from '@/graph/variables'
|
|
6
|
+
import type { GraphConfigInterface } from '@/graph/config'
|
|
6
7
|
|
|
7
8
|
export const ALPHA_MIN = 0.001
|
|
8
9
|
export const MAX_POINT_SIZE = 64
|
|
9
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Maximum number of executions to delay before performing hover detection.
|
|
13
|
+
* This threshold prevents excessive hover detection calls for performance optimization.
|
|
14
|
+
* The `findHoveredItem` method will skip actual detection until this count is reached.
|
|
15
|
+
*/
|
|
16
|
+
export const MAX_HOVER_DETECTION_DELAY = 4
|
|
17
|
+
|
|
10
18
|
export type Hovered = { index: number; position: [ number, number ] }
|
|
11
19
|
type Focused = { index: number }
|
|
12
20
|
|
|
@@ -26,6 +34,7 @@ export class Store {
|
|
|
26
34
|
public hoveredPoint: Hovered | undefined = undefined
|
|
27
35
|
public focusedPoint: Focused | undefined = undefined
|
|
28
36
|
public draggingPointIndex: number | undefined = undefined
|
|
37
|
+
public hoveredLinkIndex: number | undefined = undefined
|
|
29
38
|
public adjustedSpaceSize = defaultConfigValues.spaceSize
|
|
30
39
|
public isSpaceKeyPressed = false
|
|
31
40
|
public div: HTMLDivElement | undefined
|
|
@@ -33,10 +42,13 @@ export class Store {
|
|
|
33
42
|
|
|
34
43
|
public hoveredPointRingColor = [1, 1, 1, hoveredPointRingOpacity]
|
|
35
44
|
public focusedPointRingColor = [1, 1, 1, focusedPointRingOpacity]
|
|
45
|
+
public hoveredLinkColor = [-1, -1, -1, -1]
|
|
36
46
|
// -1 means that the color is not set
|
|
37
47
|
public greyoutPointColor = [-1, -1, -1, -1]
|
|
38
48
|
// If backgroundColor is dark, isDarkenGreyout is true
|
|
39
49
|
public isDarkenGreyout = false
|
|
50
|
+
// Whether link hovering is enabled based on configured event handlers
|
|
51
|
+
public isLinkHoveringEnabled = false
|
|
40
52
|
private alphaTarget = 0
|
|
41
53
|
private scalePointX = scaleLinear()
|
|
42
54
|
private scalePointY = scaleLinear()
|
|
@@ -102,14 +114,14 @@ export class Store {
|
|
|
102
114
|
return this.scalePointY(y)
|
|
103
115
|
}
|
|
104
116
|
|
|
105
|
-
public setHoveredPointRingColor (color: string): void {
|
|
117
|
+
public setHoveredPointRingColor (color: string | [number, number, number, number]): void {
|
|
106
118
|
const convertedRgba = getRgbaColor(color)
|
|
107
119
|
this.hoveredPointRingColor[0] = convertedRgba[0]
|
|
108
120
|
this.hoveredPointRingColor[1] = convertedRgba[1]
|
|
109
121
|
this.hoveredPointRingColor[2] = convertedRgba[2]
|
|
110
122
|
}
|
|
111
123
|
|
|
112
|
-
public setFocusedPointRingColor (color: string): void {
|
|
124
|
+
public setFocusedPointRingColor (color: string | [number, number, number, number]): void {
|
|
113
125
|
const convertedRgba = getRgbaColor(color)
|
|
114
126
|
this.focusedPointRingColor[0] = convertedRgba[0]
|
|
115
127
|
this.focusedPointRingColor[1] = convertedRgba[1]
|
|
@@ -128,6 +140,25 @@ export class Store {
|
|
|
128
140
|
this.greyoutPointColor[3] = convertedRgba[3]
|
|
129
141
|
}
|
|
130
142
|
|
|
143
|
+
public updateLinkHoveringEnabled (config: Pick<GraphConfigInterface, 'onLinkClick' | 'onLinkMouseOver' | 'onLinkMouseOut'>): void {
|
|
144
|
+
this.isLinkHoveringEnabled = !!(config.onLinkClick || config.onLinkMouseOver || config.onLinkMouseOut)
|
|
145
|
+
if (!this.isLinkHoveringEnabled) {
|
|
146
|
+
this.hoveredLinkIndex = undefined
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
public setHoveredLinkColor (color?: string | [number, number, number, number]): void {
|
|
151
|
+
if (color === undefined) {
|
|
152
|
+
this.hoveredLinkColor = [-1, -1, -1, -1]
|
|
153
|
+
return
|
|
154
|
+
}
|
|
155
|
+
const convertedRgba = getRgbaColor(color)
|
|
156
|
+
this.hoveredLinkColor[0] = convertedRgba[0]
|
|
157
|
+
this.hoveredLinkColor[1] = convertedRgba[1]
|
|
158
|
+
this.hoveredLinkColor[2] = convertedRgba[2]
|
|
159
|
+
this.hoveredLinkColor[3] = convertedRgba[3]
|
|
160
|
+
}
|
|
161
|
+
|
|
131
162
|
public setFocusedPoint (index?: number): void {
|
|
132
163
|
if (index !== undefined) {
|
|
133
164
|
this.focusedPoint = { index }
|
|
@@ -35,7 +35,8 @@ const config = {
|
|
|
35
35
|
fitViewPadding: 0.3, // centers the graph width padding of ~30% of screen
|
|
36
36
|
rescalePositions: true, // rescale positions
|
|
37
37
|
enableDrag: true, // enable dragging points
|
|
38
|
-
|
|
38
|
+
onPointClick: pointIndex => { console.log('Clicked point index: ', pointIndex) },
|
|
39
|
+
onBackgroundClick: () => { console.log('Clicked background') },
|
|
39
40
|
/* ... */
|
|
40
41
|
}
|
|
41
42
|
|
|
@@ -16,6 +16,7 @@ import { Meta } from "@storybook/blocks";
|
|
|
16
16
|
| pointOpacity | Universal opacity value applied to all points. This value multiplies with individual point alpha values (if set via setPointColors). Useful for dynamically controlling opacity of all points without updating individual RGBA arrays. | `1.0` |
|
|
17
17
|
| pointSizeScale | Scale factor for the point size | `1` |
|
|
18
18
|
| hoveredPointCursor | Cursor style to use when hovering over a point | `auto` |
|
|
19
|
+
| hoveredLinkCursor | Cursor style to use when hovering over a link | `auto` |
|
|
19
20
|
| renderHoveredPointRing | Turns ring rendering around a point on hover on / off | `false` |
|
|
20
21
|
| hoveredPointRingColor | Hovered point ring color hex value or an array of RGBA values | `white` |
|
|
21
22
|
| focusedPointRingColor | Focused point ring color hex value or an array of RGBA values | `white` |
|
|
@@ -26,6 +27,8 @@ import { Meta } from "@storybook/blocks";
|
|
|
26
27
|
| linkGreyoutOpacity | Greyed out link opacity value when the selection is active | `0.1` |
|
|
27
28
|
| linkWidth | The default width value to use for links when no link widths are provided or if the width value in the array is `undefined` or `null` | `1` |
|
|
28
29
|
| linkWidthScale | Scale factor for the link width | `1` |
|
|
30
|
+
| hoveredLinkColor | The color to use for links when they are hovered. This can be either a hex color string (e.g., '#ff3333') or an array of RGBA values in the format `[red, green, blue, alpha]` where each value is a number between 0 and 255 | `undefined` |
|
|
31
|
+
| hoveredLinkWidthIncrease | Number of pixels to add to the link width when hovered | `5` |
|
|
29
32
|
| scaleLinksOnZoom | Increase/decrease link width when zooming | `false` |
|
|
30
33
|
| curvedLinks | If set to true, links are rendered as curved lines. Otherwise as straight lines | `false` |
|
|
31
34
|
| curvedLinkSegments | Number of segments in a curved line | `19` |
|
|
@@ -86,11 +89,17 @@ cosmos.gl layout algorithm was inspired by the [d3-force](https://github.com/d3/
|
|
|
86
89
|
| onSimulationTick | Called on every simulation tick, with the current alpha value and hover information |
|
|
87
90
|
| onSimulationEnd | Called when simulation stops |
|
|
88
91
|
| onSimulationPause | Called when simulation pauses |
|
|
89
|
-
|
|
|
92
|
+
| onSimulationUnpause | Called when simulation unpauses |
|
|
93
|
+
| onSimulationRestart | **[DEPRECATED]** Called when simulation restarts. Use `onSimulationUnpause` instead |
|
|
90
94
|
| onClick | Called on canvas click with point index and position |
|
|
95
|
+
| onPointClick | Called when a point is clicked |
|
|
96
|
+
| onLinkClick | Called when a link is clicked |
|
|
97
|
+
| onBackgroundClick | Called when the background (empty space) is clicked |
|
|
91
98
|
| onMouseMove | Called on mouse movement with hover info |
|
|
92
99
|
| onPointMouseOver | Called when pointer enters a point |
|
|
93
100
|
| onPointMouseOut | Called when pointer leaves a point |
|
|
101
|
+
| onLinkMouseOver | Called when pointer enters a link |
|
|
102
|
+
| onLinkMouseOut | Called when pointer leaves a link |
|
|
94
103
|
| onZoomStart | Called when zoom/pan starts |
|
|
95
104
|
| onZoom | Called during zoom/pan |
|
|
96
105
|
| onZoomEnd | Called when zoom/pan ends |
|
|
@@ -8,11 +8,14 @@ This method sets the [cosmos.gl configuration](../?path=/docs/configuration--doc
|
|
|
8
8
|
|
|
9
9
|
* **`config`** (Object): The configuration object adhering to cosmos.gl configuration properties.
|
|
10
10
|
|
|
11
|
-
### <a name="set_point_positions" href="#set_point_positions">#</a> graph.<b>setPointPositions</b>(<i>pointPositions</i>)
|
|
11
|
+
### <a name="set_point_positions" href="#set_point_positions">#</a> graph.<b>setPointPositions</b>(<i>pointPositions</i>, [<i>dontRescale</i>])
|
|
12
12
|
|
|
13
13
|
This method sets the positions of points in a cosmos.gl graph using the provided coordinates array.
|
|
14
14
|
|
|
15
15
|
* **`pointPositions`** (Float32Array): A Float32Array representing the x and y coordinates of points in the format `[x1, y1, x2, y2, ..., xN, yN]`. Each pair represents the coordinates of a single point.
|
|
16
|
+
* **`dontRescale`** (Boolean, optional): For this call only, controls whether to rescale the points.
|
|
17
|
+
- `true`: Don't rescale the points.
|
|
18
|
+
- `false` or `undefined` (default): Use the behavior defined by `config.rescalePositions`.
|
|
16
19
|
|
|
17
20
|
**Example:**
|
|
18
21
|
```javascript
|
|
@@ -246,7 +249,7 @@ graph.render();
|
|
|
246
249
|
|
|
247
250
|
In this example, the `linkArrows` array contains three boolean values. The first value `true` sets an arrow on the first link, the second value `false` leaves the second link without an arrow, and the third value `true` sets an arrow on the third link.
|
|
248
251
|
|
|
249
|
-
### <a name="
|
|
252
|
+
### <a name="set_link_strength" href="#set_link_strength">#</a> graph.<b>setLinkStrength</b>(<i>linkStrength</i>)
|
|
250
253
|
|
|
251
254
|
This method sets the strength of the graph links.
|
|
252
255
|
|
|
@@ -298,7 +301,7 @@ This method sets the force strength coefficients for clustering points in the gr
|
|
|
298
301
|
|
|
299
302
|
The `render` method renders the graph and, optionally, controls the initial energy of the simulation.
|
|
300
303
|
|
|
301
|
-
* **`
|
|
304
|
+
* **`simulationAlpha`** (number, optional): The higher the value, the more initial energy the simulation will get. Zero value stops the simulation.
|
|
302
305
|
|
|
303
306
|
### <a name="zoom_to_point_by_index" href="#zoom_to_point_by_index">#</a> graph.<b>zoomToPointByIndex</b>(<i>index</i>, [<i>duration</i>], [<i>scale</i>], [<i>canZoomOut</i>])
|
|
304
307
|
|
|
@@ -508,7 +511,13 @@ Starts the simulation with an optional <i>alpha</i> parameter, which controls th
|
|
|
508
511
|
|
|
509
512
|
Pauses the current simulation in the graph.
|
|
510
513
|
|
|
511
|
-
### <a name="
|
|
514
|
+
### <a name="unpause" href="#unpause">#</a> graph.<b>unpause</b>()
|
|
515
|
+
|
|
516
|
+
Unpauses (resumes) the current simulation in the graph.
|
|
517
|
+
|
|
518
|
+
### <a name="restart" href="#restart">#</a> graph.<b>restart</b>() <b style={{ color: 'orange' }}>[DEPRECATED]</b>
|
|
519
|
+
|
|
520
|
+
**⚠️ Deprecated:** Use `unpause()` instead. This method will be removed in a future version.
|
|
512
521
|
|
|
513
522
|
Restarts the current simulation in the graph.
|
|
514
523
|
|
|
@@ -38,15 +38,15 @@ export const basicSetUp = (): { graph: Graph; div: HTMLDivElement} => {
|
|
|
38
38
|
simulationRepulsion: 0.2,
|
|
39
39
|
simulationGravity: 0.1,
|
|
40
40
|
simulationDecay: 100000,
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
graph.zoomToPointByIndex(index)
|
|
45
|
-
} else {
|
|
46
|
-
graph.unselectPoints()
|
|
47
|
-
}
|
|
41
|
+
onPointClick: (index: number): void => {
|
|
42
|
+
graph.selectPointByIndex(index)
|
|
43
|
+
graph.zoomToPointByIndex(index)
|
|
48
44
|
console.log('Clicked point index: ', index)
|
|
49
45
|
},
|
|
46
|
+
onBackgroundClick: (): void => {
|
|
47
|
+
graph.unselectPoints()
|
|
48
|
+
console.log('Clicked background')
|
|
49
|
+
},
|
|
50
50
|
attribution: 'visualized with <a href="https://cosmograph.app/" style="color: var(--cosmosgl-attribution-color);" target="_blank">Cosmograph</a>',
|
|
51
51
|
})
|
|
52
52
|
|
|
@@ -71,18 +71,28 @@ export const basicSetUp = (): { graph: Graph; div: HTMLDivElement} => {
|
|
|
71
71
|
graph.pause()
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
function
|
|
74
|
+
function unpause (): void {
|
|
75
75
|
isPaused = false
|
|
76
76
|
pauseButton.textContent = 'Pause'
|
|
77
|
-
graph
|
|
77
|
+
// if the graph is at 100% progress, start the graph
|
|
78
|
+
if (graph.progress === 1) {
|
|
79
|
+
graph.start()
|
|
80
|
+
} else {
|
|
81
|
+
graph.unpause()
|
|
82
|
+
}
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
function togglePause (): void {
|
|
81
|
-
if (isPaused)
|
|
86
|
+
if (isPaused) unpause()
|
|
82
87
|
else pause()
|
|
83
88
|
}
|
|
84
89
|
|
|
85
90
|
pauseButton.addEventListener('click', togglePause)
|
|
91
|
+
graph.setConfig({
|
|
92
|
+
onSimulationEnd: (): void => {
|
|
93
|
+
pause()
|
|
94
|
+
},
|
|
95
|
+
})
|
|
86
96
|
|
|
87
97
|
// Zoom and Select
|
|
88
98
|
function getRandomPointIndex (): number {
|