@hema-to/regl-scatterplot 1.14.1
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 +1110 -0
- package/dist/regl-scatterplot.esm.d.ts +126 -0
- package/dist/regl-scatterplot.esm.js +9962 -0
- package/dist/regl-scatterplot.js +9385 -0
- package/dist/regl-scatterplot.min.js +8 -0
- package/dist/types.d.ts +306 -0
- package/package.json +100 -0
- package/src/bg.fs +13 -0
- package/src/bg.vs +16 -0
- package/src/constants.js +189 -0
- package/src/index.js +4654 -0
- package/src/kdbush-class.js +369 -0
- package/src/kdbush-worker.js +20 -0
- package/src/kdbush.js +69 -0
- package/src/lasso-manager/constants.js +7 -0
- package/src/lasso-manager/create-long-press-animations.js +257 -0
- package/src/lasso-manager/create-long-press-elements.js +68 -0
- package/src/lasso-manager/index.js +781 -0
- package/src/lasso-manager/utils.js +40 -0
- package/src/point-simple.fs +10 -0
- package/src/point-update.fs +21 -0
- package/src/point-update.vs +13 -0
- package/src/point.fs +22 -0
- package/src/point.vs +124 -0
- package/src/renderer.js +252 -0
- package/src/spline-curve-worker.js +271 -0
- package/src/spline-curve.js +23 -0
- package/src/types.d.ts +306 -0
- package/src/utils.js +598 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/* eslint-env worker */
|
|
2
|
+
/* eslint no-restricted-globals: 1 */
|
|
3
|
+
|
|
4
|
+
const worker = function worker() {
|
|
5
|
+
const state = {};
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Catmull-Rom interpolation
|
|
9
|
+
* @param {number} t - Progress value
|
|
10
|
+
* @param {array} p0 - First point
|
|
11
|
+
* @param {array} p1 - Second point
|
|
12
|
+
* @param {array} p2 - Third point
|
|
13
|
+
* @param {array} p3 - Forth point
|
|
14
|
+
* @return {number} Interpolated value
|
|
15
|
+
*/
|
|
16
|
+
const catmullRom = (t, p0, p1, p2, p3) => {
|
|
17
|
+
const v0 = (p2 - p0) * 0.5;
|
|
18
|
+
const v1 = (p3 - p1) * 0.5;
|
|
19
|
+
return (
|
|
20
|
+
(2 * p1 - 2 * p2 + v0 + v1) * t * t * t +
|
|
21
|
+
(-3 * p1 + 3 * p2 - 2 * v0 - v1) * t * t +
|
|
22
|
+
v0 * t +
|
|
23
|
+
p1
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Interpolate a point with Catmull-Rom
|
|
29
|
+
* @param {number} t - Progress value
|
|
30
|
+
* @param {array} points - Key points
|
|
31
|
+
* @param {number} maxPointIdx - Highest point index. Same as array.length - 1
|
|
32
|
+
* @return {array} Interpolated point
|
|
33
|
+
*/
|
|
34
|
+
const interpolatePoint = (t, points, maxPointIdx) => {
|
|
35
|
+
const p = maxPointIdx * t;
|
|
36
|
+
|
|
37
|
+
const intPoint = Math.floor(p);
|
|
38
|
+
const weight = p - intPoint;
|
|
39
|
+
|
|
40
|
+
const p0 = points[Math.max(0, intPoint - 1)];
|
|
41
|
+
const p1 = points[intPoint];
|
|
42
|
+
const p2 = points[Math.min(maxPointIdx, intPoint + 1)];
|
|
43
|
+
const p3 = points[Math.min(maxPointIdx, intPoint + 2)];
|
|
44
|
+
|
|
45
|
+
return [
|
|
46
|
+
catmullRom(weight, p0[0], p1[0], p2[0], p3[0]),
|
|
47
|
+
catmullRom(weight, p0[1], p1[1], p2[1], p3[1]),
|
|
48
|
+
];
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Square distance
|
|
53
|
+
* @param {number} x1 - First x coordinate
|
|
54
|
+
* @param {number} y1 - First y coordinate
|
|
55
|
+
* @param {number} x2 - Second x coordinate
|
|
56
|
+
* @param {number} y2 - Second y coordinate
|
|
57
|
+
* @return {number} Distance
|
|
58
|
+
*/
|
|
59
|
+
const sqDist = (x1, y1, x2, y2) => (x1 - x2) ** 2 + (y1 - y2) ** 2;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Douglas Peucker square segment distance
|
|
63
|
+
* Implementation from https://github.com/mourner/simplify-js
|
|
64
|
+
* @author Vladimir Agafonkin
|
|
65
|
+
* @copyright Vladimir Agafonkin 2013
|
|
66
|
+
* @license BSD
|
|
67
|
+
* @param {array} p - Point
|
|
68
|
+
* @param {array} p1 - First boundary point
|
|
69
|
+
* @param {array} p2 - Second boundary point
|
|
70
|
+
* @return {number} Distance
|
|
71
|
+
*/
|
|
72
|
+
const sqSegDist = (p, p1, p2) => {
|
|
73
|
+
let x = p1[0];
|
|
74
|
+
let y = p1[1];
|
|
75
|
+
let dx = p2[0] - x;
|
|
76
|
+
let dy = p2[1] - y;
|
|
77
|
+
|
|
78
|
+
if (dx !== 0 || dy !== 0) {
|
|
79
|
+
const t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy);
|
|
80
|
+
|
|
81
|
+
if (t > 1) {
|
|
82
|
+
x = p2[0];
|
|
83
|
+
y = p2[1];
|
|
84
|
+
} else if (t > 0) {
|
|
85
|
+
x += dx * t;
|
|
86
|
+
y += dy * t;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
dx = p[0] - x;
|
|
91
|
+
dy = p[1] - y;
|
|
92
|
+
|
|
93
|
+
return dx * dx + dy * dy;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Douglas Peucker step function
|
|
98
|
+
* Implementation from https://github.com/mourner/simplify-js
|
|
99
|
+
* @author Vladimir Agafonkin
|
|
100
|
+
* @copyright Vladimir Agafonkin 2013
|
|
101
|
+
* @license BSD
|
|
102
|
+
* @param {[type]} points [description]
|
|
103
|
+
* @param {[type]} first [description]
|
|
104
|
+
* @param {[type]} last [description]
|
|
105
|
+
* @param {[type]} tolerance [description]
|
|
106
|
+
* @param {[type]} simplified [description]
|
|
107
|
+
* @return {[type]} [description]
|
|
108
|
+
*/
|
|
109
|
+
// biome-ignore lint/style/useNamingConvention: DP stands for Douglas Peucker
|
|
110
|
+
const simplifyDPStep = (points, first, last, tolerance, simplified) => {
|
|
111
|
+
let maxDist = tolerance;
|
|
112
|
+
let index;
|
|
113
|
+
|
|
114
|
+
for (let i = first + 1; i < last; i++) {
|
|
115
|
+
const dist = sqSegDist(points[i], points[first], points[last]);
|
|
116
|
+
|
|
117
|
+
if (dist > maxDist) {
|
|
118
|
+
index = i;
|
|
119
|
+
maxDist = dist;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (maxDist > tolerance) {
|
|
124
|
+
if (index - first > 1) {
|
|
125
|
+
simplifyDPStep(points, first, index, tolerance, simplified);
|
|
126
|
+
}
|
|
127
|
+
simplified.push(points[index]);
|
|
128
|
+
if (last - index > 1) {
|
|
129
|
+
simplifyDPStep(points, index, last, tolerance, simplified);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Douglas Peucker. Implementation from https://github.com/mourner/simplify-js
|
|
136
|
+
* @author Vladimir Agafonkin
|
|
137
|
+
* @copyright Vladimir Agafonkin 2013
|
|
138
|
+
* @license BSD
|
|
139
|
+
* @param {array} points - List of points to be simplified
|
|
140
|
+
* @param {number} tolerance - Tolerance level. Points below this distance level will be ignored
|
|
141
|
+
* @return {array} Simplified point list
|
|
142
|
+
*/
|
|
143
|
+
const simplifyDouglasPeucker = (points, tolerance) => {
|
|
144
|
+
const last = points.length - 1;
|
|
145
|
+
const simplified = [points[0]];
|
|
146
|
+
|
|
147
|
+
simplifyDPStep(points, 0, last, tolerance, simplified);
|
|
148
|
+
simplified.push(points[last]);
|
|
149
|
+
|
|
150
|
+
return simplified;
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Interpolate intermediate points between key points
|
|
155
|
+
* @param {array} points - Fixed key points
|
|
156
|
+
* @param {number} options.maxIntPointsPerSegment - Maximum number of points between two key points
|
|
157
|
+
* @param {number} options.tolerance - Simplification tolerance
|
|
158
|
+
* @return {array} Interpolated points including key points
|
|
159
|
+
*/
|
|
160
|
+
const interpolatePoints = (
|
|
161
|
+
points,
|
|
162
|
+
{ maxIntPointsPerSegment = 100, tolerance = 0.002 } = {},
|
|
163
|
+
) => {
|
|
164
|
+
const numPoints = points.length;
|
|
165
|
+
const maxPointIdx = numPoints - 1;
|
|
166
|
+
|
|
167
|
+
const maxOutPoints = maxPointIdx * maxIntPointsPerSegment + 1;
|
|
168
|
+
const sqTolerance = tolerance ** 2;
|
|
169
|
+
|
|
170
|
+
let outPoints = [];
|
|
171
|
+
let prevPoint;
|
|
172
|
+
|
|
173
|
+
// Generate interpolated points where the squared-distance between points
|
|
174
|
+
// is larger than sqTolerance
|
|
175
|
+
for (let i = 0; i < numPoints - 1; i++) {
|
|
176
|
+
let segmentPoints = [points[i].slice(0, 2)];
|
|
177
|
+
prevPoint = points[i];
|
|
178
|
+
|
|
179
|
+
for (let j = 1; j < maxIntPointsPerSegment; j++) {
|
|
180
|
+
const t = (i * maxIntPointsPerSegment + j) / maxOutPoints;
|
|
181
|
+
const intPoint = interpolatePoint(t, points, maxPointIdx);
|
|
182
|
+
|
|
183
|
+
// Check squared distance simplification
|
|
184
|
+
if (
|
|
185
|
+
sqDist(prevPoint[0], prevPoint[1], intPoint[0], intPoint[1]) >
|
|
186
|
+
sqTolerance
|
|
187
|
+
) {
|
|
188
|
+
segmentPoints.push(intPoint);
|
|
189
|
+
prevPoint = intPoint;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Add next key point. Needed for the simplification algorithm
|
|
194
|
+
segmentPoints.push(points[i + 1]);
|
|
195
|
+
// Simplify interpolated points using the douglas-peuckner algorithm
|
|
196
|
+
segmentPoints = simplifyDouglasPeucker(segmentPoints, sqTolerance);
|
|
197
|
+
// Add simplified points without the last key point, which is added
|
|
198
|
+
// anyway in the next segment
|
|
199
|
+
outPoints = outPoints.concat(
|
|
200
|
+
segmentPoints.slice(0, segmentPoints.length - 1),
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
outPoints.push(points[points.length - 1].slice(0, 2));
|
|
204
|
+
|
|
205
|
+
return outPoints.flat();
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Group points by line assignment (the fifth component of a point)
|
|
210
|
+
* @param {array} points - Flat list of points
|
|
211
|
+
* @return {array} List of lists of ordered points by line
|
|
212
|
+
*/
|
|
213
|
+
const groupPoints = (points) => {
|
|
214
|
+
const groupedPoints = {};
|
|
215
|
+
|
|
216
|
+
const isOrdered = !Number.isNaN(+points[0][5]);
|
|
217
|
+
// biome-ignore lint/complexity/noForEach: somehow for .. of does not work in a worker
|
|
218
|
+
points.forEach((point) => {
|
|
219
|
+
const segId = point[4];
|
|
220
|
+
|
|
221
|
+
if (!groupedPoints[segId]) {
|
|
222
|
+
groupedPoints[segId] = [];
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
if (isOrdered) {
|
|
226
|
+
groupedPoints[segId][point[5]] = point;
|
|
227
|
+
} else {
|
|
228
|
+
groupedPoints[segId].push(point);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// The filtering ensures that non-existing array entries are removed
|
|
233
|
+
// biome-ignore lint/complexity/noForEach: somehow for .. of does not work in a worker
|
|
234
|
+
Object.entries(groupedPoints).forEach((idPoints) => {
|
|
235
|
+
groupedPoints[idPoints[0]] = idPoints[1].filter((v) => v);
|
|
236
|
+
// Store the first point as the reference
|
|
237
|
+
groupedPoints[idPoints[0]].reference = idPoints[1][0];
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
return groupedPoints;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
self.onmessage = function onmessage(event) {
|
|
244
|
+
const numPoints = event.data.points ? +event.data.points.length : 0;
|
|
245
|
+
|
|
246
|
+
if (!numPoints) {
|
|
247
|
+
self.postMessage({ error: new Error('No points provided') });
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
state.points = event.data.points;
|
|
251
|
+
|
|
252
|
+
const groupedPoints = groupPoints(event.data.points);
|
|
253
|
+
|
|
254
|
+
self.postMessage({
|
|
255
|
+
points: Object.entries(groupedPoints).reduce(
|
|
256
|
+
(curvePoints, idAndPoints) => {
|
|
257
|
+
curvePoints[idAndPoints[0]] = interpolatePoints(
|
|
258
|
+
idAndPoints[1],
|
|
259
|
+
event.data.options,
|
|
260
|
+
);
|
|
261
|
+
// Make sure the reference is passed on
|
|
262
|
+
curvePoints[idAndPoints[0]].reference = idAndPoints[1].reference;
|
|
263
|
+
return curvePoints;
|
|
264
|
+
},
|
|
265
|
+
{},
|
|
266
|
+
),
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
export default worker;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createWorker } from '@flekschas/utils';
|
|
2
|
+
import workerFn from './spline-curve-worker.js';
|
|
3
|
+
|
|
4
|
+
const createSplineCurve = (
|
|
5
|
+
points,
|
|
6
|
+
options = { tolerance: 0.002, maxIntPointsPerSegment: 100 },
|
|
7
|
+
) =>
|
|
8
|
+
new Promise((resolve, reject) => {
|
|
9
|
+
const worker = createWorker(workerFn);
|
|
10
|
+
|
|
11
|
+
worker.onmessage = (e) => {
|
|
12
|
+
if (e.data.error) {
|
|
13
|
+
reject(e.data.error);
|
|
14
|
+
} else {
|
|
15
|
+
resolve(e.data.points);
|
|
16
|
+
}
|
|
17
|
+
worker.terminate();
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
worker.postMessage({ points, options });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default createSplineCurve;
|
package/src/types.d.ts
ADDED
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
type Hex = string;
|
|
2
|
+
type Rgb = [number, number, number];
|
|
3
|
+
type Rgba = [number, number, number, number];
|
|
4
|
+
|
|
5
|
+
type Color = Hex | Rgb | Rgba;
|
|
6
|
+
type ColorMap = Color | Color[];
|
|
7
|
+
|
|
8
|
+
type Category = 'category' | 'value1' | 'valueA' | 'valueZ' | 'z';
|
|
9
|
+
type Value = 'value' | 'value2' | 'valueB' | 'valueW' | 'w';
|
|
10
|
+
type DataEncoding = Category | Value;
|
|
11
|
+
type PointDataEncoding = DataEncoding | 'inherit' | 'segment';
|
|
12
|
+
|
|
13
|
+
type KeyAction = 'lasso' | 'rotate' | 'merge';
|
|
14
|
+
type KeyMap = Record<'alt' | 'cmd' | 'ctrl' | 'meta' | 'shift', KeyAction>;
|
|
15
|
+
|
|
16
|
+
type MouseMode = 'panZoom' | 'lasso' | 'rotate';
|
|
17
|
+
|
|
18
|
+
type PointScaleMode = 'constant' | 'asinh' | 'linear';
|
|
19
|
+
|
|
20
|
+
// biome-ignore lint/style/useNamingConvention: ZWData are three words, z, w, and data
|
|
21
|
+
type ZWDataType = 'continuous' | 'categorical';
|
|
22
|
+
|
|
23
|
+
// biome-ignore lint/suspicious/noExplicitAny: Untyped external library
|
|
24
|
+
type Camera2D = any; // Needs to be typed at some point
|
|
25
|
+
type Scale = import('d3-scale').ScaleContinuousNumeric<number, number>;
|
|
26
|
+
|
|
27
|
+
type PointsObject = {
|
|
28
|
+
x: ArrayLike<number>;
|
|
29
|
+
y: ArrayLike<number>;
|
|
30
|
+
line?: ArrayLike<number>;
|
|
31
|
+
lineOrder?: ArrayLike<number>;
|
|
32
|
+
} & {
|
|
33
|
+
[Key in Category | Value]?: ArrayLike<number>;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type Points = number[][] | PointsObject;
|
|
37
|
+
|
|
38
|
+
type PointOptions = {
|
|
39
|
+
color: ColorMap;
|
|
40
|
+
colorActive: Color;
|
|
41
|
+
colorHover: Color;
|
|
42
|
+
outlineWidth: number;
|
|
43
|
+
size: number | number[];
|
|
44
|
+
sizeSelected: number;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
type PointConnectionOptions = {
|
|
48
|
+
color: ColorMap;
|
|
49
|
+
colorActive: Color;
|
|
50
|
+
colorHover: Color;
|
|
51
|
+
opacity: number | number[];
|
|
52
|
+
opacityActive: number;
|
|
53
|
+
size: number | number[];
|
|
54
|
+
sizeActive: number;
|
|
55
|
+
maxIntPointsPerSegment: number;
|
|
56
|
+
tolerance: number;
|
|
57
|
+
// Nullifiable
|
|
58
|
+
colorBy: null | PointDataEncoding;
|
|
59
|
+
opacityBy: null | PointDataEncoding;
|
|
60
|
+
sizeBy: null | PointDataEncoding;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
type LassoOptions = {
|
|
64
|
+
color: Color;
|
|
65
|
+
lineWidth: number;
|
|
66
|
+
minDelay: number;
|
|
67
|
+
minDist: number;
|
|
68
|
+
mode: 'intersect' | 'merge' | 'remove' | null;
|
|
69
|
+
clearEvent: 'lassoEnd' | 'deselect';
|
|
70
|
+
initiator: boolean;
|
|
71
|
+
initiatorParentElement: HTMLElement;
|
|
72
|
+
onLongPress: boolean;
|
|
73
|
+
longPressTime: number;
|
|
74
|
+
longPressAfterEffectTime: number;
|
|
75
|
+
longPressEffectDelay: number;
|
|
76
|
+
longPressRevertEffectTime: number;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
type CameraOptions = {
|
|
80
|
+
target: [number, number];
|
|
81
|
+
distance: number;
|
|
82
|
+
rotation: number;
|
|
83
|
+
view: Float32Array;
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// biome-ignore lint/correctness/noUnusedVariables: Imported from ./index.js
|
|
87
|
+
type Rect = {
|
|
88
|
+
x: number;
|
|
89
|
+
y: number;
|
|
90
|
+
width: number;
|
|
91
|
+
height: number;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
interface BaseAnnotation {
|
|
95
|
+
lineColor?: Color;
|
|
96
|
+
lineWidth?: number;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// biome-ignore lint/style/useNamingConvention: HLine stands for HorizontalLine
|
|
100
|
+
interface AnnotationHLine extends BaseAnnotation {
|
|
101
|
+
y: number;
|
|
102
|
+
x1?: number;
|
|
103
|
+
x2?: number;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// biome-ignore lint/style/useNamingConvention: HLine stands for VerticalLine
|
|
107
|
+
interface AnnotationVLine extends BaseAnnotation {
|
|
108
|
+
x: number;
|
|
109
|
+
y1?: number;
|
|
110
|
+
y2?: number;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
interface AnnotationDomRect extends BaseAnnotation {
|
|
114
|
+
x: number;
|
|
115
|
+
y: number;
|
|
116
|
+
width: number;
|
|
117
|
+
height: number;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface AnnotationRect extends BaseAnnotation {
|
|
121
|
+
x1: number;
|
|
122
|
+
y1: number;
|
|
123
|
+
x2: number;
|
|
124
|
+
y2: number;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
interface AnnotationPolygon extends BaseAnnotation {
|
|
128
|
+
vertices: [number, number][];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// biome-ignore lint/correctness/noUnusedVariables: Imported from ./index.js
|
|
132
|
+
type Annotation =
|
|
133
|
+
| AnnotationHLine
|
|
134
|
+
| AnnotationVLine
|
|
135
|
+
| AnnotationDomRect
|
|
136
|
+
| AnnotationRect
|
|
137
|
+
| AnnotationPolygon;
|
|
138
|
+
|
|
139
|
+
interface BaseOptions {
|
|
140
|
+
backgroundColor: Color;
|
|
141
|
+
deselectOnDblClick: boolean;
|
|
142
|
+
deselectOnEscape: boolean;
|
|
143
|
+
actionKeyMap: KeyMap;
|
|
144
|
+
keyMap: KeyMap;
|
|
145
|
+
mouseMode: MouseMode;
|
|
146
|
+
showPointConnections: boolean;
|
|
147
|
+
showReticle: boolean;
|
|
148
|
+
reticleColor: Color;
|
|
149
|
+
opacity: number | number[];
|
|
150
|
+
opacityByDensityFill: number;
|
|
151
|
+
opacityInactiveMax: number;
|
|
152
|
+
opacityInactiveScale: number;
|
|
153
|
+
height: 'auto' | number;
|
|
154
|
+
width: 'auto' | number;
|
|
155
|
+
gamma: number;
|
|
156
|
+
aspectRatio: number;
|
|
157
|
+
annotationLineColor: Color;
|
|
158
|
+
annotationLineWidth: number;
|
|
159
|
+
// biome-ignore lint/style/useNamingConvention: HVLine stands for HorizontalVerticalLine
|
|
160
|
+
annotationHVLineLimit: number;
|
|
161
|
+
// Nullifiable
|
|
162
|
+
backgroundImage: null | import('regl').Texture2D | string;
|
|
163
|
+
colorBy: null | DataEncoding;
|
|
164
|
+
sizeBy: null | DataEncoding;
|
|
165
|
+
opacityBy: null | DataEncoding;
|
|
166
|
+
xScale: null | Scale;
|
|
167
|
+
yScale: null | Scale;
|
|
168
|
+
pointScaleMode: PointScaleMode;
|
|
169
|
+
cameraIsFixed: boolean;
|
|
170
|
+
antiAliasing: number;
|
|
171
|
+
pixelAligned: boolean;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// biome-ignore lint/style/useNamingConvention: KDBush is a library name
|
|
175
|
+
export interface CreateKDBushOptions {
|
|
176
|
+
node: number;
|
|
177
|
+
useWorker: boolean;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Helper type. Adds a prefix to keys of Options.
|
|
182
|
+
*
|
|
183
|
+
* type A = { a: number; b: string };
|
|
184
|
+
* WithPrefix<'myPrefix', A> === { myPrefixA: number, myPrefixB: string };
|
|
185
|
+
*/
|
|
186
|
+
type WithPrefix<
|
|
187
|
+
Name extends string,
|
|
188
|
+
Options extends Record<string, unknown>,
|
|
189
|
+
> = {
|
|
190
|
+
[Key in keyof Options as `${Name}${Capitalize<string & Key>}`]: Options[Key];
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export type Settable = BaseOptions &
|
|
194
|
+
WithPrefix<'point', PointOptions> &
|
|
195
|
+
WithPrefix<'pointConnection', PointConnectionOptions> &
|
|
196
|
+
WithPrefix<'lasso', LassoOptions> &
|
|
197
|
+
WithPrefix<'camera', CameraOptions>;
|
|
198
|
+
|
|
199
|
+
export type RendererOptions = {
|
|
200
|
+
regl: import('regl').Regl;
|
|
201
|
+
canvas: HTMLCanvasElement;
|
|
202
|
+
gamma: number;
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export type Properties = {
|
|
206
|
+
renderer: ReturnType<typeof import('./renderer').createRenderer>;
|
|
207
|
+
canvas: HTMLCanvasElement;
|
|
208
|
+
regl: import('regl').Regl;
|
|
209
|
+
syncEvents: boolean;
|
|
210
|
+
version: string;
|
|
211
|
+
lassoInitiatorElement: HTMLElement;
|
|
212
|
+
lassoLongPressIndicatorParentElement: HTMLElement;
|
|
213
|
+
camera: Camera2D;
|
|
214
|
+
performanceMode: boolean;
|
|
215
|
+
renderPointsAsSquares: boolean;
|
|
216
|
+
disableAlphaBlending: boolean;
|
|
217
|
+
opacityByDensityDebounceTime: number;
|
|
218
|
+
spatialIndex: ArrayBuffer;
|
|
219
|
+
spatialIndexUseWorker: undefined | boolean;
|
|
220
|
+
points: [number, number][];
|
|
221
|
+
pointsInView: number[];
|
|
222
|
+
isDestroyed: boolean;
|
|
223
|
+
isPointsDrawn: boolean;
|
|
224
|
+
isPointsFiltered: boolean;
|
|
225
|
+
hoveredPoint: number;
|
|
226
|
+
filteredPoints: number[];
|
|
227
|
+
selectedPoints: number[];
|
|
228
|
+
} & Settable;
|
|
229
|
+
|
|
230
|
+
// Options for plot.{draw, select, hover}
|
|
231
|
+
export interface ScatterplotMethodOptions {
|
|
232
|
+
draw: Partial<{
|
|
233
|
+
transition: boolean;
|
|
234
|
+
transitionDuration: number;
|
|
235
|
+
transitionEasing: (t: number) => number;
|
|
236
|
+
preventFilterReset: boolean;
|
|
237
|
+
hover: number;
|
|
238
|
+
select: number | number[];
|
|
239
|
+
filter: number | number[];
|
|
240
|
+
zDataType: ZWDataType;
|
|
241
|
+
wDataType: ZWDataType;
|
|
242
|
+
spatialIndex: ArrayBuffer;
|
|
243
|
+
}>;
|
|
244
|
+
hover: Partial<{
|
|
245
|
+
showReticleOnce: boolean;
|
|
246
|
+
preventEvent: boolean;
|
|
247
|
+
}>;
|
|
248
|
+
select: Partial<{
|
|
249
|
+
merge: boolean;
|
|
250
|
+
remove: boolean;
|
|
251
|
+
preventEvent: boolean;
|
|
252
|
+
}>;
|
|
253
|
+
filter: Partial<{
|
|
254
|
+
preventEvent: boolean;
|
|
255
|
+
}>;
|
|
256
|
+
preventEvent: Partial<{
|
|
257
|
+
preventEvent: boolean;
|
|
258
|
+
}>;
|
|
259
|
+
zoomToPoints: Partial<{
|
|
260
|
+
padding: number;
|
|
261
|
+
transition: boolean;
|
|
262
|
+
transitionDuration: number;
|
|
263
|
+
transitionEasing: (t: number) => number;
|
|
264
|
+
}>;
|
|
265
|
+
zoomToArea: Partial<{
|
|
266
|
+
transition: boolean;
|
|
267
|
+
transitionDuration: number;
|
|
268
|
+
transitionEasing: (t: number) => number;
|
|
269
|
+
}>;
|
|
270
|
+
zoomToLocation: Partial<{
|
|
271
|
+
transition: boolean;
|
|
272
|
+
transitionDuration: number;
|
|
273
|
+
transitionEasing: (t: number) => number;
|
|
274
|
+
}>;
|
|
275
|
+
export: Partial<{
|
|
276
|
+
scale: number;
|
|
277
|
+
antiAliasing: number;
|
|
278
|
+
pixelAligned: boolean;
|
|
279
|
+
}>;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export type Events = import('pub-sub-es').Event<
|
|
283
|
+
| 'init'
|
|
284
|
+
| 'destroy'
|
|
285
|
+
| 'backgroundImageReady'
|
|
286
|
+
| 'deselect'
|
|
287
|
+
| 'unfilter'
|
|
288
|
+
| 'lassoStart'
|
|
289
|
+
| 'transitionStart'
|
|
290
|
+
| 'pointConnectionsDraw',
|
|
291
|
+
undefined
|
|
292
|
+
> &
|
|
293
|
+
import('pub-sub-es').Event<
|
|
294
|
+
'lassoEnd' | 'lassoExtend',
|
|
295
|
+
{ coordinates: number[] }
|
|
296
|
+
> &
|
|
297
|
+
import('pub-sub-es').Event<'pointOver' | 'pointOut', number> &
|
|
298
|
+
import('pub-sub-es').Event<'select' | 'focus', { points: number[] }> &
|
|
299
|
+
import('pub-sub-es').Event<'points', { points: number[][] }> &
|
|
300
|
+
import('pub-sub-es').Event<'transitionEnd', import('regl').Regl> &
|
|
301
|
+
import('pub-sub-es').Event<
|
|
302
|
+
'view' | 'draw' | 'drawing',
|
|
303
|
+
Pick<Properties, 'camera' | 'xScale' | 'yScale'> & {
|
|
304
|
+
view: Properties['cameraView'];
|
|
305
|
+
}
|
|
306
|
+
>;
|