@genome-spy/core 0.47.0 → 0.48.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/dist/bundle/index.es.js +3332 -3209
- package/dist/bundle/index.js +84 -84
- package/dist/schema.json +9 -2
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +10 -3
- package/dist/src/marks/link.common.glsl.js +1 -1
- package/dist/src/marks/link.d.ts.map +1 -1
- package/dist/src/marks/link.js +14 -22
- package/dist/src/marks/link.vertex.glsl.js +1 -1
- package/dist/src/marks/mark.d.ts +9 -0
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +19 -0
- package/dist/src/marks/rect.vertex.glsl.js +1 -1
- package/dist/src/spec/mark.d.ts +1 -1
- package/dist/src/utils/animator.d.ts +7 -4
- package/dist/src/utils/animator.d.ts.map +1 -1
- package/dist/src/utils/animator.js +45 -17
- package/dist/src/utils/inertia.d.ts +5 -1
- package/dist/src/utils/inertia.d.ts.map +1 -1
- package/dist/src/utils/inertia.js +6 -5
- package/dist/src/utils/ringBuffer.d.ts +19 -0
- package/dist/src/utils/ringBuffer.d.ts.map +1 -0
- package/dist/src/utils/ringBuffer.js +43 -0
- package/dist/src/utils/ringBuffer.test.js +39 -0
- package/dist/src/view/gridView.d.ts +5 -1
- package/dist/src/view/gridView.d.ts.map +1 -1
- package/dist/src/view/gridView.js +10 -8
- package/dist/src/view/layout/point.d.ts +17 -1
- package/dist/src/view/layout/point.d.ts.map +1 -1
- package/dist/src/view/layout/point.js +36 -1
- package/dist/src/view/zoom.d.ts +3 -9
- package/dist/src/view/zoom.d.ts.map +1 -1
- package/dist/src/view/zoom.js +133 -8
- package/package.json +2 -2
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export default class Point {
|
|
2
|
+
/**
|
|
3
|
+
* @param {MouseEvent} event
|
|
4
|
+
*/
|
|
5
|
+
static fromMouseEvent(event: MouseEvent): Point;
|
|
2
6
|
/**
|
|
3
7
|
*
|
|
4
8
|
* @param {number} x
|
|
@@ -8,7 +12,19 @@ export default class Point {
|
|
|
8
12
|
/** @readonly */ readonly x: number;
|
|
9
13
|
/** @readonly */ readonly y: number;
|
|
10
14
|
/**
|
|
11
|
-
*
|
|
15
|
+
* @param {Point} point
|
|
16
|
+
*/
|
|
17
|
+
subtract(point: Point): Point;
|
|
18
|
+
/**
|
|
19
|
+
* @param {Point} point
|
|
20
|
+
*/
|
|
21
|
+
add(point: Point): Point;
|
|
22
|
+
/**
|
|
23
|
+
* @param {number} scalar
|
|
24
|
+
*/
|
|
25
|
+
multiply(scalar: number): Point;
|
|
26
|
+
get length(): number;
|
|
27
|
+
/**
|
|
12
28
|
* @param {Point} point
|
|
13
29
|
*/
|
|
14
30
|
equals(point: Point): boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../../src/view/layout/point.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../../src/view/layout/point.js"],"names":[],"mappings":"AAIA;IACI;;OAEG;IACH,6BAFW,UAAU,SAIpB;IAED;;;;OAIG;IACH,eAHW,MAAM,KACN,MAAM,EAKhB;IAFG,gBAAgB,CAAC,mBAAU;IAC3B,gBAAgB,CAAC,mBAAU;IAG/B;;OAEG;IACH,gBAFW,KAAK,SAIf;IAED;;OAEG;IACH,WAFW,KAAK,SAIf;IAED;;OAEG;IACH,iBAFW,MAAM,SAIhB;IAED,qBAEC;IAED;;OAEG;IACH,cAFW,KAAK,WAQf;CACJ"}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Hmm. This looks quite a bit like a two-dimensional vector.
|
|
3
|
+
* Maybe we should use a vector instead?
|
|
4
|
+
*/
|
|
1
5
|
export default class Point {
|
|
6
|
+
/**
|
|
7
|
+
* @param {MouseEvent} event
|
|
8
|
+
*/
|
|
9
|
+
static fromMouseEvent(event) {
|
|
10
|
+
return new Point(event.clientX, event.clientY);
|
|
11
|
+
}
|
|
12
|
+
|
|
2
13
|
/**
|
|
3
14
|
*
|
|
4
15
|
* @param {number} x
|
|
@@ -10,7 +21,31 @@ export default class Point {
|
|
|
10
21
|
}
|
|
11
22
|
|
|
12
23
|
/**
|
|
13
|
-
*
|
|
24
|
+
* @param {Point} point
|
|
25
|
+
*/
|
|
26
|
+
subtract(point) {
|
|
27
|
+
return new Point(this.x - point.x, this.y - point.y);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {Point} point
|
|
32
|
+
*/
|
|
33
|
+
add(point) {
|
|
34
|
+
return new Point(this.x - point.x, this.y - point.y);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {number} scalar
|
|
39
|
+
*/
|
|
40
|
+
multiply(scalar) {
|
|
41
|
+
return new Point(this.x * scalar, this.y * scalar);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get length() {
|
|
45
|
+
return Math.sqrt(this.x ** 2 + this.y ** 2);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
14
49
|
* @param {Point} point
|
|
15
50
|
*/
|
|
16
51
|
equals(point) {
|
package/dist/src/view/zoom.d.ts
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
* @typedef {object} ZoomEvent
|
|
3
|
-
* @prop {number} x
|
|
4
|
-
* @prop {number} y
|
|
5
|
-
* @prop {number} xDelta
|
|
6
|
-
* @prop {number} yDelta
|
|
7
|
-
* @prop {number} zDelta
|
|
8
|
-
*/
|
|
1
|
+
export function isStillZooming(): boolean;
|
|
9
2
|
/**
|
|
10
3
|
* @param {import("../utils/interactionEvent.js").default} event
|
|
11
4
|
* @param {import("./layout/rectangle.js").default} coords
|
|
12
5
|
* @param {(zoomEvent: ZoomEvent) => void} handleZoom
|
|
13
6
|
* @param {import("../types/viewContext.js").Hover} [hover]
|
|
7
|
+
* @param {import("../utils/animator.js").default} [animator]
|
|
14
8
|
*/
|
|
15
|
-
export
|
|
9
|
+
export function interactionToZoom(event: import("../utils/interactionEvent.js").default, coords: import("./layout/rectangle.js").default, handleZoom: (zoomEvent: ZoomEvent) => void, hover?: import("../types/viewContext.js").Hover, animator?: import("../utils/animator.js").default): void;
|
|
16
10
|
export type ZoomEvent = {
|
|
17
11
|
x: number;
|
|
18
12
|
y: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"zoom.d.ts","sourceRoot":"","sources":["../../../src/view/zoom.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"zoom.d.ts","sourceRoot":"","sources":["../../../src/view/zoom.js"],"names":[],"mappings":"AAkBA,0CAGC;AAgBD;;;;;;GAMG;AACH,yCANW,OAAO,8BAA8B,EAAE,OAAO,UAC9C,OAAO,uBAAuB,EAAE,OAAO,0BAC3B,SAAS,KAAK,IAAI,UAC9B,OAAO,yBAAyB,EAAE,KAAK,aACvC,OAAO,sBAAsB,EAAE,OAAO,QAkJhD;;OA1LS,MAAM;OACN,MAAM;YACN,MAAM;YACN,MAAM;YACN,MAAM"}
|
package/dist/src/view/zoom.js
CHANGED
|
@@ -7,19 +7,60 @@
|
|
|
7
7
|
* @prop {number} zDelta
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import { makeLerpSmoother } from "../utils/animator.js";
|
|
11
|
+
import RingBuffer from "../utils/ringBuffer.js";
|
|
12
|
+
import Point from "./layout/point.js";
|
|
13
|
+
|
|
14
|
+
/** @type {ReturnType<typeof makeLerpSmoother>} */
|
|
15
|
+
let smoother;
|
|
16
|
+
|
|
17
|
+
let lastTimestamp = 0;
|
|
18
|
+
|
|
19
|
+
export function isStillZooming() {
|
|
20
|
+
const delta = performance.now() - lastTimestamp;
|
|
21
|
+
return delta < 50;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param {T} fn
|
|
27
|
+
* @returns {T}
|
|
28
|
+
* @template {Function} T
|
|
29
|
+
*/
|
|
30
|
+
function recordTimeStamp(fn) {
|
|
31
|
+
// @ts-ignore
|
|
32
|
+
return function (...args) {
|
|
33
|
+
lastTimestamp = performance.now();
|
|
34
|
+
fn(...args);
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
10
38
|
/**
|
|
11
39
|
* @param {import("../utils/interactionEvent.js").default} event
|
|
12
40
|
* @param {import("./layout/rectangle.js").default} coords
|
|
13
41
|
* @param {(zoomEvent: ZoomEvent) => void} handleZoom
|
|
14
42
|
* @param {import("../types/viewContext.js").Hover} [hover]
|
|
43
|
+
* @param {import("../utils/animator.js").default} [animator]
|
|
15
44
|
*/
|
|
16
|
-
export
|
|
45
|
+
export function interactionToZoom(event, coords, handleZoom, hover, animator) {
|
|
46
|
+
handleZoom = recordTimeStamp(handleZoom);
|
|
47
|
+
|
|
17
48
|
if (event.type == "wheel") {
|
|
49
|
+
// TODO: Wheel-zoom inertia should probably be moved here and the faked wheel
|
|
50
|
+
// events in genomeSpy.js and inertia.js should be retired.
|
|
51
|
+
|
|
18
52
|
event.uiEvent.preventDefault(); // TODO: Only if there was something zoomable
|
|
19
53
|
|
|
20
54
|
const wheelEvent = /** @type {WheelEvent} */ (event.uiEvent);
|
|
21
55
|
const wheelMultiplier = wheelEvent.deltaMode ? 120 : 1;
|
|
22
56
|
|
|
57
|
+
if (!wheelEvent.deltaX && !wheelEvent.deltaY) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Stop drag-to-pan inertia
|
|
62
|
+
smoother?.stop();
|
|
63
|
+
|
|
23
64
|
let { x, y } = event.point;
|
|
24
65
|
|
|
25
66
|
// Snapping to the hovered item:
|
|
@@ -59,31 +100,115 @@ export default function interactionToZoom(event, coords, handleZoom, hover) {
|
|
|
59
100
|
event.type == "mousedown" &&
|
|
60
101
|
/** @type {MouseEvent} */ (event.uiEvent).button === 0
|
|
61
102
|
) {
|
|
103
|
+
if (smoother) {
|
|
104
|
+
smoother.stop();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** @type {RingBuffer<{point: Point, timestamp: number}>} */
|
|
108
|
+
const eventBuffer = new RingBuffer(30);
|
|
109
|
+
|
|
62
110
|
const mouseEvent = /** @type {MouseEvent} */ (event.uiEvent);
|
|
63
111
|
mouseEvent.preventDefault();
|
|
64
112
|
|
|
65
|
-
let
|
|
113
|
+
let prevPoint = Point.fromMouseEvent(mouseEvent);
|
|
66
114
|
|
|
67
115
|
const onMousemove = /** @param {MouseEvent} moveEvent */ (
|
|
68
116
|
moveEvent
|
|
69
117
|
) => {
|
|
118
|
+
const point = Point.fromMouseEvent(moveEvent);
|
|
119
|
+
eventBuffer.push({ point, timestamp: performance.now() });
|
|
120
|
+
|
|
121
|
+
const delta = point.subtract(prevPoint);
|
|
122
|
+
|
|
70
123
|
handleZoom({
|
|
71
|
-
x:
|
|
72
|
-
y:
|
|
73
|
-
xDelta:
|
|
74
|
-
yDelta:
|
|
124
|
+
x: prevPoint.x,
|
|
125
|
+
y: prevPoint.y,
|
|
126
|
+
xDelta: delta.x,
|
|
127
|
+
yDelta: delta.y,
|
|
75
128
|
zDelta: 0,
|
|
76
129
|
});
|
|
77
130
|
|
|
78
|
-
|
|
131
|
+
prevPoint = point;
|
|
79
132
|
};
|
|
80
133
|
|
|
81
|
-
const
|
|
134
|
+
const animateInertia = () => {
|
|
135
|
+
const lastMillisToInclude = 160;
|
|
136
|
+
|
|
137
|
+
const now = performance.now();
|
|
138
|
+
const arr = eventBuffer
|
|
139
|
+
.get()
|
|
140
|
+
.filter((p) => now - p.timestamp < lastMillisToInclude);
|
|
141
|
+
|
|
142
|
+
if (arr.length < 5 || !animator || isDecelerating(arr)) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const a = arr.at(-1);
|
|
147
|
+
const b = arr[0];
|
|
148
|
+
|
|
149
|
+
const v = a.point
|
|
150
|
+
.subtract(b.point)
|
|
151
|
+
.multiply(1 / (a.timestamp - b.timestamp));
|
|
152
|
+
|
|
153
|
+
let x = prevPoint.x;
|
|
154
|
+
let y = prevPoint.y;
|
|
155
|
+
|
|
156
|
+
smoother = makeLerpSmoother(
|
|
157
|
+
animator,
|
|
158
|
+
(p) => {
|
|
159
|
+
handleZoom({
|
|
160
|
+
x: p.x,
|
|
161
|
+
y: p.y,
|
|
162
|
+
xDelta: x - p.x,
|
|
163
|
+
yDelta: y - p.y,
|
|
164
|
+
zDelta: 0,
|
|
165
|
+
});
|
|
166
|
+
x = p.x;
|
|
167
|
+
y = p.y;
|
|
168
|
+
},
|
|
169
|
+
150,
|
|
170
|
+
0.5,
|
|
171
|
+
{ x, y }
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
smoother({
|
|
175
|
+
x: prevPoint.x - v.x * 250,
|
|
176
|
+
y: prevPoint.y - v.y * 250,
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const onMouseup = () => {
|
|
82
181
|
document.removeEventListener("mousemove", onMousemove);
|
|
83
182
|
document.removeEventListener("mouseup", onMouseup);
|
|
183
|
+
animateInertia();
|
|
84
184
|
};
|
|
85
185
|
|
|
86
186
|
document.addEventListener("mouseup", onMouseup, false);
|
|
87
187
|
document.addEventListener("mousemove", onMousemove, false);
|
|
88
188
|
}
|
|
89
189
|
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Split the array into two vectors and compare their lengths to find out if
|
|
193
|
+
* the mouse movement is decelerating.
|
|
194
|
+
* @param {{point: Point, timestamp: number}[]} arr
|
|
195
|
+
*/
|
|
196
|
+
function isDecelerating(arr) {
|
|
197
|
+
const mid = arr[Math.floor(arr.length / 2)];
|
|
198
|
+
|
|
199
|
+
const ap = mid.point
|
|
200
|
+
.subtract(arr[0].point)
|
|
201
|
+
.multiply(mid.timestamp - arr[0].timestamp);
|
|
202
|
+
const bp = arr
|
|
203
|
+
.at(-1)
|
|
204
|
+
.point.subtract(mid.point)
|
|
205
|
+
.multiply(arr.at(-1).timestamp - mid.timestamp);
|
|
206
|
+
|
|
207
|
+
const a = ap.length;
|
|
208
|
+
const b = bp.length;
|
|
209
|
+
|
|
210
|
+
// Found by trial and error
|
|
211
|
+
const maxRatio = 0.4;
|
|
212
|
+
|
|
213
|
+
return b / a < maxRatio;
|
|
214
|
+
}
|
package/package.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
},
|
|
8
8
|
"contributors": [],
|
|
9
9
|
"license": "MIT",
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.48.1",
|
|
11
11
|
"jsdelivr": "dist/bundle/index.js",
|
|
12
12
|
"unpkg": "dist/bundle/index.js",
|
|
13
13
|
"browser": "dist/bundle/index.js",
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"vega-scale": "^7.3.1",
|
|
65
65
|
"vega-util": "^1.17.2"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "f2e023ce43cf18091cb81140f5be1f59887271df"
|
|
68
68
|
}
|