@cosmos.gl/graph 2.2.1 → 2.3.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/.github/dco.yml +4 -0
- package/README.md +7 -7
- package/dist/config.d.ts +16 -0
- package/dist/helper.d.ts +13 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +5777 -5149
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +63 -53
- package/dist/index.min.js.map +1 -1
- package/dist/modules/Points/index.d.ts +5 -0
- package/dist/variables.d.ts +2 -0
- package/package.json +3 -1
- package/src/config.ts +21 -0
- package/src/helper.ts +22 -0
- package/src/index.ts +81 -5
- package/src/modules/Lines/draw-curve-line.frag +2 -1
- package/src/modules/Lines/draw-curve-line.vert +9 -3
- package/src/modules/Lines/index.ts +1 -0
- package/src/modules/Points/draw-highlighted.vert +2 -1
- package/src/modules/Points/draw-points.vert +2 -1
- package/src/modules/Points/index.ts +43 -0
- package/src/stories/2. configuration.mdx +2 -0
- package/src/stories/3. api-reference.mdx +55 -18
- package/src/stories/clusters/worm.ts +22 -1
- package/src/variables.ts +2 -0
|
@@ -55,6 +55,11 @@ export declare class Points extends CoreModule {
|
|
|
55
55
|
trackPointsByIndices(indices?: number[] | undefined): void;
|
|
56
56
|
getTrackedPositionsMap(): Map<number, [number, number]>;
|
|
57
57
|
getSampledPointPositionsMap(): Map<number, [number, number]>;
|
|
58
|
+
getSampledPoints(): {
|
|
59
|
+
indices: number[];
|
|
60
|
+
positions: number[];
|
|
61
|
+
};
|
|
62
|
+
getTrackedPositionsArray(): number[];
|
|
58
63
|
private swapFbo;
|
|
59
64
|
private rescaleInitialNodePositions;
|
|
60
65
|
}
|
package/dist/variables.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export declare const defaultPointColor = "#b3b3b3";
|
|
2
2
|
export declare const defaultGreyoutPointOpacity: undefined;
|
|
3
3
|
export declare const defaultGreyoutPointColor: undefined;
|
|
4
|
+
export declare const defaultPointOpacity = 1;
|
|
4
5
|
export declare const defaultPointSize = 4;
|
|
5
6
|
export declare const defaultLinkColor = "#666666";
|
|
6
7
|
export declare const defaultGreyoutLinkOpacity = 0.1;
|
|
8
|
+
export declare const defaultLinkOpacity = 1;
|
|
7
9
|
export declare const defaultLinkWidth = 1;
|
|
8
10
|
export declare const defaultBackgroundColor = "#222222";
|
|
9
11
|
export declare const defaultConfigValues: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmos.gl/graph",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "GPU-based force graph layout and rendering",
|
|
5
5
|
"jsdelivr": "dist/index.min.js",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"@types/d3-selection": "^3.0.2",
|
|
54
54
|
"@types/d3-transition": "^3.0.1",
|
|
55
55
|
"@types/d3-zoom": "^3.0.1",
|
|
56
|
+
"@types/dompurify": "^3.0.5",
|
|
56
57
|
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
|
57
58
|
"@typescript-eslint/parser": "^5.30.5",
|
|
58
59
|
"@zerollup/ts-transform-paths": "^1.7.18",
|
|
@@ -84,6 +85,7 @@
|
|
|
84
85
|
"d3-selection": "^3.0.0",
|
|
85
86
|
"d3-transition": "^3.0.1",
|
|
86
87
|
"d3-zoom": "^3.0.0",
|
|
88
|
+
"dompurify": "^3.2.6",
|
|
87
89
|
"gl-bench": "^1.0.42",
|
|
88
90
|
"gl-matrix": "^3.4.3",
|
|
89
91
|
"random": "^4.1.0",
|
package/src/config.ts
CHANGED
|
@@ -4,9 +4,11 @@ import {
|
|
|
4
4
|
defaultPointColor,
|
|
5
5
|
defaultGreyoutPointOpacity,
|
|
6
6
|
defaultGreyoutPointColor,
|
|
7
|
+
defaultPointOpacity,
|
|
7
8
|
defaultPointSize,
|
|
8
9
|
defaultLinkColor,
|
|
9
10
|
defaultGreyoutLinkOpacity,
|
|
11
|
+
defaultLinkOpacity,
|
|
10
12
|
defaultLinkWidth,
|
|
11
13
|
defaultBackgroundColor,
|
|
12
14
|
defaultConfigValues,
|
|
@@ -74,6 +76,15 @@ export interface GraphConfigInterface {
|
|
|
74
76
|
* Default value: `4`
|
|
75
77
|
*/
|
|
76
78
|
pointSize?: number;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Universal opacity value applied to all points.
|
|
82
|
+
* This value multiplies with individual point alpha values (if set via setPointColors).
|
|
83
|
+
* Useful for dynamically controlling opacity of all points without updating individual RGBA arrays.
|
|
84
|
+
* Default value: `1.0`
|
|
85
|
+
*/
|
|
86
|
+
pointOpacity?: number;
|
|
87
|
+
|
|
77
88
|
/**
|
|
78
89
|
* Scale factor for the point size.
|
|
79
90
|
* Default value: `1`
|
|
@@ -128,6 +139,14 @@ export interface GraphConfigInterface {
|
|
|
128
139
|
*/
|
|
129
140
|
linkColor?: string | [number, number, number, number];
|
|
130
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Universal opacity value applied to all links.
|
|
144
|
+
* This value multiplies with individual link alpha values (if set via setLinkColors).
|
|
145
|
+
* Useful for dynamically controlling opacity of all links without updating individual RGBA arrays.
|
|
146
|
+
* Default value: `1.0`
|
|
147
|
+
*/
|
|
148
|
+
linkOpacity?: number;
|
|
149
|
+
|
|
131
150
|
/**
|
|
132
151
|
* Greyed out link opacity value when the selection is active.
|
|
133
152
|
* Default value: `0.1`
|
|
@@ -517,6 +536,7 @@ export class GraphConfig implements GraphConfigInterface {
|
|
|
517
536
|
public pointGreyoutOpacity = defaultGreyoutPointOpacity
|
|
518
537
|
public pointGreyoutColor = defaultGreyoutPointColor
|
|
519
538
|
public pointSize = defaultPointSize
|
|
539
|
+
public pointOpacity = defaultPointOpacity
|
|
520
540
|
public pointSizeScale = defaultConfigValues.pointSizeScale
|
|
521
541
|
public hoveredPointCursor = defaultConfigValues.hoveredPointCursor
|
|
522
542
|
public renderHoveredPointRing = defaultConfigValues.renderHoveredPointRing
|
|
@@ -524,6 +544,7 @@ export class GraphConfig implements GraphConfigInterface {
|
|
|
524
544
|
public focusedPointRingColor = defaultConfigValues.focusedPointRingColor
|
|
525
545
|
public focusedPointIndex = defaultConfigValues.focusedPointIndex
|
|
526
546
|
public linkColor = defaultLinkColor
|
|
547
|
+
public linkOpacity = defaultLinkOpacity
|
|
527
548
|
public linkGreyoutOpacity = defaultGreyoutLinkOpacity
|
|
528
549
|
public linkWidth = defaultLinkWidth
|
|
529
550
|
public linkWidthScale = defaultConfigValues.linkWidthScale
|
package/src/helper.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { color as d3Color } from 'd3-color'
|
|
2
2
|
import regl from 'regl'
|
|
3
|
+
import DOMPurify from 'dompurify'
|
|
3
4
|
|
|
4
5
|
export const isFunction = <T>(a: T): boolean => typeof a === 'function'
|
|
5
6
|
export const isArray = <T>(a: unknown | T[]): a is T[] => Array.isArray(a)
|
|
@@ -50,3 +51,24 @@ export function clamp (num: number, min: number, max: number): number {
|
|
|
50
51
|
export function isNumber (value: number | undefined | null | typeof NaN): boolean {
|
|
51
52
|
return value !== undefined && value !== null && !Number.isNaN(value)
|
|
52
53
|
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Sanitizes HTML content to prevent XSS attacks using DOMPurify
|
|
57
|
+
*
|
|
58
|
+
* This function is used internally to sanitize HTML content before setting innerHTML,
|
|
59
|
+
* such as in attribution text. It uses a safe default configuration that allows
|
|
60
|
+
* only common safe HTML elements and attributes.
|
|
61
|
+
*
|
|
62
|
+
* @param html The HTML string to sanitize
|
|
63
|
+
* @param options Optional DOMPurify configuration options to override defaults
|
|
64
|
+
* @returns Sanitized HTML string safe for innerHTML usage
|
|
65
|
+
*/
|
|
66
|
+
export function sanitizeHtml (html: string, options?: DOMPurify.Config): string {
|
|
67
|
+
return DOMPurify.sanitize(html, {
|
|
68
|
+
// Default configuration: allow common safe HTML elements and attributes
|
|
69
|
+
ALLOWED_TAGS: ['a', 'b', 'i', 'em', 'strong', 'span', 'div', 'p', 'br'],
|
|
70
|
+
ALLOWED_ATTR: ['href', 'target', 'class', 'id', 'style'],
|
|
71
|
+
ALLOW_DATA_ATTR: false,
|
|
72
|
+
...options,
|
|
73
|
+
})
|
|
74
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { D3ZoomEvent } from 'd3-zoom'
|
|
|
5
5
|
import { D3DragEvent } from 'd3-drag'
|
|
6
6
|
import regl from 'regl'
|
|
7
7
|
import { GraphConfig, GraphConfigInterface } from '@/graph/config'
|
|
8
|
-
import { getRgbaColor, readPixels } from '@/graph/helper'
|
|
8
|
+
import { getRgbaColor, readPixels, sanitizeHtml } from '@/graph/helper'
|
|
9
9
|
import { ForceCenter } from '@/graph/modules/ForceCenter'
|
|
10
10
|
import { ForceGravity } from '@/graph/modules/ForceGravity'
|
|
11
11
|
import { ForceLink, LinkDirection } from '@/graph/modules/ForceLink'
|
|
@@ -322,6 +322,17 @@ export class Graph {
|
|
|
322
322
|
this._needsPointColorUpdate = true
|
|
323
323
|
}
|
|
324
324
|
|
|
325
|
+
/**
|
|
326
|
+
* Gets the current colors of the graph points.
|
|
327
|
+
*
|
|
328
|
+
* @returns {Float32Array} A Float32Array representing the colors of points in the format [r1, g1, b1, a1, r2, g2, b2, a2, ..., rn, gn, bn, an],
|
|
329
|
+
* where each color is in RGBA format. Returns an empty Float32Array if no point colors are set.
|
|
330
|
+
*/
|
|
331
|
+
public getPointColors (): Float32Array {
|
|
332
|
+
if (this._isDestroyed) return new Float32Array()
|
|
333
|
+
return this.graph.pointColors ?? new Float32Array()
|
|
334
|
+
}
|
|
335
|
+
|
|
325
336
|
/**
|
|
326
337
|
* Sets the sizes for the graph points.
|
|
327
338
|
*
|
|
@@ -335,6 +346,17 @@ export class Graph {
|
|
|
335
346
|
this._needsPointSizeUpdate = true
|
|
336
347
|
}
|
|
337
348
|
|
|
349
|
+
/**
|
|
350
|
+
* Gets the current sizes of the graph points.
|
|
351
|
+
*
|
|
352
|
+
* @returns {Float32Array} A Float32Array representing the sizes of points in the format [size1, size2, ..., sizen],
|
|
353
|
+
* where `n` is the index of the point. Returns an empty Float32Array if no point sizes are set.
|
|
354
|
+
*/
|
|
355
|
+
public getPointSizes (): Float32Array {
|
|
356
|
+
if (this._isDestroyed) return new Float32Array()
|
|
357
|
+
return this.graph.pointSizes ?? new Float32Array()
|
|
358
|
+
}
|
|
359
|
+
|
|
338
360
|
/**
|
|
339
361
|
* Sets the links for the graph.
|
|
340
362
|
*
|
|
@@ -367,6 +389,17 @@ export class Graph {
|
|
|
367
389
|
this._needsLinkColorUpdate = true
|
|
368
390
|
}
|
|
369
391
|
|
|
392
|
+
/**
|
|
393
|
+
* Gets the current colors of the graph links.
|
|
394
|
+
*
|
|
395
|
+
* @returns {Float32Array} A Float32Array representing the colors of links in the format [r1, g1, b1, a1, r2, g2, b2, a2, ..., rn, gn, bn, an],
|
|
396
|
+
* where each color is in RGBA format. Returns an empty Float32Array if no link colors are set.
|
|
397
|
+
*/
|
|
398
|
+
public getLinkColors (): Float32Array {
|
|
399
|
+
if (this._isDestroyed) return new Float32Array()
|
|
400
|
+
return this.graph.linkColors ?? new Float32Array()
|
|
401
|
+
}
|
|
402
|
+
|
|
370
403
|
/**
|
|
371
404
|
* Sets the widths for the graph links.
|
|
372
405
|
*
|
|
@@ -380,6 +413,17 @@ export class Graph {
|
|
|
380
413
|
this._needsLinkWidthUpdate = true
|
|
381
414
|
}
|
|
382
415
|
|
|
416
|
+
/**
|
|
417
|
+
* Gets the current widths of the graph links.
|
|
418
|
+
*
|
|
419
|
+
* @returns {Float32Array} A Float32Array representing the widths of links in the format [width1, width2, ..., widthn],
|
|
420
|
+
* where `n` is the index of the link. Returns an empty Float32Array if no link widths are set.
|
|
421
|
+
*/
|
|
422
|
+
public getLinkWidths (): Float32Array {
|
|
423
|
+
if (this._isDestroyed) return new Float32Array()
|
|
424
|
+
return this.graph.linkWidths ?? new Float32Array()
|
|
425
|
+
}
|
|
426
|
+
|
|
383
427
|
/**
|
|
384
428
|
* Sets the arrows for the graph links.
|
|
385
429
|
*
|
|
@@ -882,6 +926,17 @@ export class Graph {
|
|
|
882
926
|
return this.points.getTrackedPositionsMap()
|
|
883
927
|
}
|
|
884
928
|
|
|
929
|
+
/**
|
|
930
|
+
* Get current X and Y coordinates of the tracked points as an array.
|
|
931
|
+
* @returns Array of point positions in the format [x1, y1, x2, y2, ..., xn, yn] for tracked points only.
|
|
932
|
+
* The positions are ordered by the tracking indices (same order as provided to trackPointPositionsByIndices).
|
|
933
|
+
* Returns an empty array if no points are being tracked.
|
|
934
|
+
*/
|
|
935
|
+
public getTrackedPointPositionsArray (): number[] {
|
|
936
|
+
if (this._isDestroyed || !this.points) return []
|
|
937
|
+
return this.points.getTrackedPositionsArray()
|
|
938
|
+
}
|
|
939
|
+
|
|
885
940
|
/**
|
|
886
941
|
* For the points that are currently visible on the screen, get a sample of point indices with their coordinates.
|
|
887
942
|
* The resulting number of points will depend on the `pointSamplingDistance` configuration property,
|
|
@@ -893,6 +948,17 @@ export class Graph {
|
|
|
893
948
|
return this.points.getSampledPointPositionsMap()
|
|
894
949
|
}
|
|
895
950
|
|
|
951
|
+
/**
|
|
952
|
+
* For the points that are currently visible on the screen, get a sample of point indices and positions.
|
|
953
|
+
* The resulting number of points will depend on the `pointSamplingDistance` configuration property,
|
|
954
|
+
* and the sampled points will be evenly distributed.
|
|
955
|
+
* @returns An object containing arrays of point indices and positions.
|
|
956
|
+
*/
|
|
957
|
+
public getSampledPoints (): { indices: number[]; positions: number[] } {
|
|
958
|
+
if (this._isDestroyed || !this.points) return { indices: [], positions: [] }
|
|
959
|
+
return this.points.getSampledPoints()
|
|
960
|
+
}
|
|
961
|
+
|
|
896
962
|
/**
|
|
897
963
|
* Gets the X-axis of rescaling function.
|
|
898
964
|
*
|
|
@@ -920,10 +986,15 @@ export class Graph {
|
|
|
920
986
|
public start (alpha = 1): void {
|
|
921
987
|
if (this._isDestroyed) return
|
|
922
988
|
if (!this.graph.pointsNumber) return
|
|
923
|
-
|
|
989
|
+
|
|
990
|
+
// Only start the simulation if alpha > 0
|
|
991
|
+
if (alpha > 0) {
|
|
992
|
+
this.store.isSimulationRunning = true
|
|
993
|
+
this.store.simulationProgress = 0
|
|
994
|
+
this.config.onSimulationStart?.()
|
|
995
|
+
}
|
|
996
|
+
|
|
924
997
|
this.store.alpha = alpha
|
|
925
|
-
this.store.simulationProgress = 0
|
|
926
|
-
this.config.onSimulationStart?.()
|
|
927
998
|
this.stopFrames()
|
|
928
999
|
this.frame()
|
|
929
1000
|
}
|
|
@@ -1330,7 +1401,12 @@ export class Graph {
|
|
|
1330
1401
|
font-size: 0.7rem;
|
|
1331
1402
|
font-family: inherit;
|
|
1332
1403
|
`
|
|
1333
|
-
|
|
1404
|
+
// Sanitize the attribution HTML content to prevent XSS attacks
|
|
1405
|
+
// Use more permissive settings for attribution since it's controlled by the library user
|
|
1406
|
+
this.attributionDivElement.innerHTML = sanitizeHtml(this.config.attribution, {
|
|
1407
|
+
ALLOWED_TAGS: ['a', 'b', 'i', 'em', 'strong', 'span', 'div', 'p', 'br', 'img'],
|
|
1408
|
+
ALLOWED_ATTR: ['href', 'target', 'class', 'id', 'style', 'src', 'alt', 'title'],
|
|
1409
|
+
})
|
|
1334
1410
|
this.store.div?.appendChild(this.attributionDivElement)
|
|
1335
1411
|
}
|
|
1336
1412
|
}
|
|
@@ -5,6 +5,7 @@ varying vec2 pos;
|
|
|
5
5
|
varying float arrowLength;
|
|
6
6
|
varying float useArrow;
|
|
7
7
|
varying float smoothing;
|
|
8
|
+
varying float arrowWidthFactor;
|
|
8
9
|
|
|
9
10
|
float map(float value, float min1, float max1, float min2, float max2) {
|
|
10
11
|
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
|
@@ -17,7 +18,7 @@ void main() {
|
|
|
17
18
|
if (useArrow > 0.5) {
|
|
18
19
|
float end_arrow = 0.5 + arrowLength / 2.0;
|
|
19
20
|
float start_arrow = end_arrow - arrowLength;
|
|
20
|
-
float arrowWidthDelta = 0
|
|
21
|
+
float arrowWidthDelta = arrowWidthFactor / 2.0;
|
|
21
22
|
float linkOpacity = rgbaColor.a * smoothstep(0.5 - arrowWidthDelta, 0.5 - arrowWidthDelta - smoothing / 2.0, abs(pos.y));
|
|
22
23
|
float arrowOpacity = 1.0;
|
|
23
24
|
if (pos.x > start_arrow && pos.x < start_arrow + arrowLength) {
|
|
@@ -15,6 +15,7 @@ uniform float spaceSize;
|
|
|
15
15
|
uniform vec2 screenSize;
|
|
16
16
|
uniform vec2 linkVisibilityDistanceRange;
|
|
17
17
|
uniform float linkVisibilityMinTransparency;
|
|
18
|
+
uniform float linkOpacity;
|
|
18
19
|
uniform float greyoutOpacity;
|
|
19
20
|
uniform float curvedWeight;
|
|
20
21
|
uniform float curvedLinkControlPointDistance;
|
|
@@ -27,6 +28,7 @@ varying vec2 pos;
|
|
|
27
28
|
varying float arrowLength;
|
|
28
29
|
varying float useArrow;
|
|
29
30
|
varying float smoothing;
|
|
31
|
+
varying float arrowWidthFactor;
|
|
30
32
|
|
|
31
33
|
float map(float value, float min1, float max1, float min2, float max2) {
|
|
32
34
|
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
|
|
@@ -95,9 +97,11 @@ void main() {
|
|
|
95
97
|
float linkWidth = width * widthScale;
|
|
96
98
|
float k = 2.0;
|
|
97
99
|
// Arrow width is proportionally larger than the line width
|
|
98
|
-
float arrowWidth =
|
|
100
|
+
float arrowWidth = linkWidth * k;
|
|
99
101
|
arrowWidth *= arrowSizeScale;
|
|
100
102
|
|
|
103
|
+
float arrowWidthDifference = arrowWidth - linkWidth;
|
|
104
|
+
|
|
101
105
|
// Calculate arrow width in pixels
|
|
102
106
|
float arrowWidthPx = calculateArrowWidth(arrowWidth);
|
|
103
107
|
|
|
@@ -108,9 +112,11 @@ void main() {
|
|
|
108
112
|
|
|
109
113
|
useArrow = arrow;
|
|
110
114
|
if (useArrow > 0.5) {
|
|
111
|
-
linkWidth
|
|
115
|
+
linkWidth += arrowWidthDifference;
|
|
112
116
|
}
|
|
113
117
|
|
|
118
|
+
arrowWidthFactor = arrowWidthDifference / linkWidth;
|
|
119
|
+
|
|
114
120
|
// Calculate final link width in pixels with smoothing
|
|
115
121
|
float linkWidthPx = calculateLinkWidth(linkWidth);
|
|
116
122
|
float smoothingPx = 0.5 / transformationMatrix[0][0];
|
|
@@ -120,7 +126,7 @@ void main() {
|
|
|
120
126
|
// Calculate final color with opacity based on link distance
|
|
121
127
|
vec3 rgbColor = color.rgb;
|
|
122
128
|
// Adjust opacity based on link distance
|
|
123
|
-
float opacity = color.a * max(linkVisibilityMinTransparency, map(linkDistPx, linkVisibilityDistanceRange.g, linkVisibilityDistanceRange.r, 0.0, 1.0));
|
|
129
|
+
float opacity = color.a * linkOpacity * max(linkVisibilityMinTransparency, map(linkDistPx, linkVisibilityDistanceRange.g, linkVisibilityDistanceRange.r, 0.0, 1.0));
|
|
124
130
|
|
|
125
131
|
// Apply greyed out opacity if either endpoint is greyed out
|
|
126
132
|
if (greyoutStatusA.r > 0.0 || greyoutStatusB.r > 0.0) {
|
|
@@ -69,6 +69,7 @@ export class Lines extends CoreModule {
|
|
|
69
69
|
screenSize: () => store.screenSize,
|
|
70
70
|
linkVisibilityDistanceRange: () => config.linkVisibilityDistanceRange,
|
|
71
71
|
linkVisibilityMinTransparency: () => config.linkVisibilityMinTransparency,
|
|
72
|
+
linkOpacity: () => config.linkOpacity,
|
|
72
73
|
greyoutOpacity: () => config.linkGreyoutOpacity,
|
|
73
74
|
scaleLinksOnZoom: () => config.scaleLinksOnZoom,
|
|
74
75
|
maxPointSize: () => store.maxPointSize,
|
|
@@ -14,6 +14,7 @@ uniform bool scalePointsOnZoom;
|
|
|
14
14
|
uniform float pointIndex;
|
|
15
15
|
uniform float maxPointSize;
|
|
16
16
|
uniform vec4 color;
|
|
17
|
+
uniform float universalPointOpacity;
|
|
17
18
|
uniform float greyoutOpacity;
|
|
18
19
|
uniform bool darkenGreyout;
|
|
19
20
|
uniform vec4 backgroundColor;
|
|
@@ -41,7 +42,7 @@ void main () {
|
|
|
41
42
|
vec4 pointPosition = texture2D(positionsTexture, textureCoordinates / pointsTextureSize);
|
|
42
43
|
|
|
43
44
|
rgbColor = color.rgb;
|
|
44
|
-
pointOpacity = color.a;
|
|
45
|
+
pointOpacity = color.a * universalPointOpacity;
|
|
45
46
|
vec4 greyoutStatus = texture2D(pointGreyoutStatusTexture, textureCoordinates / pointsTextureSize);
|
|
46
47
|
if (greyoutStatus.r > 0.0) {
|
|
47
48
|
if (greyoutColor[0] != -1.0) {
|
|
@@ -15,6 +15,7 @@ uniform float sizeScale;
|
|
|
15
15
|
uniform float spaceSize;
|
|
16
16
|
uniform vec2 screenSize;
|
|
17
17
|
uniform float greyoutOpacity;
|
|
18
|
+
uniform float pointOpacity;
|
|
18
19
|
uniform vec4 greyoutColor;
|
|
19
20
|
uniform vec4 backgroundColor;
|
|
20
21
|
uniform bool scalePointsOnZoom;
|
|
@@ -51,7 +52,7 @@ void main() {
|
|
|
51
52
|
gl_PointSize = calculatePointSize(size * sizeScale);
|
|
52
53
|
|
|
53
54
|
rgbColor = color.rgb;
|
|
54
|
-
alpha = color.a;
|
|
55
|
+
alpha = color.a * pointOpacity;
|
|
55
56
|
|
|
56
57
|
// Adjust alpha of selected points
|
|
57
58
|
vec4 greyoutStatus = texture2D(pointGreyoutStatus, (textureCoords + 0.5) / pointsTextureSize);
|
|
@@ -232,6 +232,7 @@ export class Points extends CoreModule {
|
|
|
232
232
|
transformationMatrix: () => store.transform,
|
|
233
233
|
spaceSize: () => store.adjustedSpaceSize,
|
|
234
234
|
screenSize: () => store.screenSize,
|
|
235
|
+
pointOpacity: () => config.pointOpacity,
|
|
235
236
|
greyoutOpacity: () => config.pointGreyoutOpacity ?? -1,
|
|
236
237
|
greyoutColor: () => store.greyoutPointColor,
|
|
237
238
|
backgroundColor: () => store.backgroundColor,
|
|
@@ -412,6 +413,7 @@ export class Points extends CoreModule {
|
|
|
412
413
|
scalePointsOnZoom: () => config.scalePointsOnZoom,
|
|
413
414
|
maxPointSize: () => store.maxPointSize,
|
|
414
415
|
pointGreyoutStatusTexture: () => this.greyoutStatusFbo,
|
|
416
|
+
universalPointOpacity: () => config.pointOpacity,
|
|
415
417
|
greyoutOpacity: () => config.pointGreyoutOpacity ?? -1,
|
|
416
418
|
darkenGreyout: () => store.darkenGreyout,
|
|
417
419
|
backgroundColor: () => store.backgroundColor,
|
|
@@ -695,6 +697,47 @@ export class Points extends CoreModule {
|
|
|
695
697
|
return positions
|
|
696
698
|
}
|
|
697
699
|
|
|
700
|
+
public getSampledPoints (): { indices: number[]; positions: number[] } {
|
|
701
|
+
const indices: number[] = []
|
|
702
|
+
const positions: number[] = []
|
|
703
|
+
if (!this.sampledPointsFbo) return { indices, positions }
|
|
704
|
+
|
|
705
|
+
this.clearSampledPointsFboCommand?.()
|
|
706
|
+
this.fillSampledPointsFboCommand?.()
|
|
707
|
+
const pixels = readPixels(this.reglInstance, this.sampledPointsFbo as regl.Framebuffer2D)
|
|
708
|
+
|
|
709
|
+
for (let i = 0; i < pixels.length / 4; i++) {
|
|
710
|
+
const index = pixels[i * 4]
|
|
711
|
+
const isNotEmpty = !!pixels[i * 4 + 1]
|
|
712
|
+
const x = pixels[i * 4 + 2]
|
|
713
|
+
const y = pixels[i * 4 + 3]
|
|
714
|
+
|
|
715
|
+
if (isNotEmpty && index !== undefined && x !== undefined && y !== undefined) {
|
|
716
|
+
indices.push(index)
|
|
717
|
+
positions.push(x, y)
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
return { indices, positions }
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
public getTrackedPositionsArray (): number[] {
|
|
725
|
+
const positions: number[] = []
|
|
726
|
+
if (!this.trackedIndices) return positions
|
|
727
|
+
positions.length = this.trackedIndices.length * 2
|
|
728
|
+
const pixels = readPixels(this.reglInstance, this.trackedPositionsFbo as regl.Framebuffer2D)
|
|
729
|
+
for (let i = 0; i < pixels.length / 4; i += 1) {
|
|
730
|
+
const x = pixels[i * 4]
|
|
731
|
+
const y = pixels[i * 4 + 1]
|
|
732
|
+
const index = this.trackedIndices[i]
|
|
733
|
+
if (x !== undefined && y !== undefined && index !== undefined) {
|
|
734
|
+
positions[i * 2] = x
|
|
735
|
+
positions[i * 2 + 1] = y
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
return positions
|
|
739
|
+
}
|
|
740
|
+
|
|
698
741
|
private swapFbo (): void {
|
|
699
742
|
const temp = this.previousPositionFbo
|
|
700
743
|
this.previousPositionFbo = this.currentPositionFbo
|
|
@@ -13,6 +13,7 @@ import { Meta } from "@storybook/blocks";
|
|
|
13
13
|
| pointGreyoutOpacity | Greyed out point opacity value when the selection is active | `undefined` |
|
|
14
14
|
| pointGreyoutColor | Greyed out point color value when the selection is active | `undefined` |
|
|
15
15
|
| pointSize | The default size value to use for points when no point sizes are provided or if the size value in the array is `undefined` or `null` | `4` |
|
|
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` |
|
|
16
17
|
| pointSizeScale | Scale factor for the point size | `1` |
|
|
17
18
|
| hoveredPointCursor | Cursor style to use when hovering over a point | `auto` |
|
|
18
19
|
| renderHoveredPointRing | Turns ring rendering around a point on hover on / off | `false` |
|
|
@@ -21,6 +22,7 @@ import { Meta } from "@storybook/blocks";
|
|
|
21
22
|
| focusedPointIndex | Set focus on a point by index. A ring will be highlighted around the focused point. When set to `undefined`, no point is focused. | `undefined` |
|
|
22
23
|
| renderLinks | Turns link rendering on / off | `true` |
|
|
23
24
|
| linkColor | The default color to use for links when no link colors are provided, or if the color value in the array is `undefined` or `null`. This can be either a hex color string (e.g., '#666666') or an array of RGBA values in the format `[red, green, blue, alpha]` where each value is a number between 0 and 255 | `#666666` |
|
|
25
|
+
| linkOpacity | Universal opacity value applied to all links. This value multiplies with individual link alpha values (if set via setLinkColors). Useful for dynamically controlling opacity of all links without updating individual RGBA arrays. | `1.0` |
|
|
24
26
|
| linkGreyoutOpacity | Greyed out link opacity value when the selection is active | `0.1` |
|
|
25
27
|
| 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` |
|
|
26
28
|
| linkWidthScale | Scale factor for the link width | `1` |
|