@genome-spy/core 0.46.1 → 0.48.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/bundle/index.es.js +5310 -5113
- package/dist/bundle/index.js +105 -94
- package/dist/schema.json +38 -0
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +31 -16
- package/dist/src/gl/webGLHelper.d.ts +2 -1
- package/dist/src/gl/webGLHelper.d.ts.map +1 -1
- package/dist/src/gl/webGLHelper.js +8 -1
- package/dist/src/marks/mark.d.ts +24 -12
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +27 -13
- package/dist/src/marks/point.d.ts +0 -1
- package/dist/src/marks/point.d.ts.map +1 -1
- package/dist/src/marks/point.js +6 -2
- package/dist/src/marks/text.d.ts.map +1 -1
- package/dist/src/marks/text.js +4 -1
- package/dist/src/scale/scale.js +2 -0
- package/dist/src/spec/parameter.d.ts +20 -1
- package/dist/src/types/embedApi.d.ts +7 -0
- package/dist/src/types/rendering.d.ts +6 -0
- package/dist/src/utils/animator.d.ts +17 -0
- package/dist/src/utils/animator.d.ts.map +1 -1
- package/dist/src/utils/animator.js +72 -0
- package/dist/src/utils/inertia.d.ts +6 -15
- package/dist/src/utils/inertia.d.ts.map +1 -1
- package/dist/src/utils/inertia.js +28 -63
- package/dist/src/utils/inputBinding.d.ts.map +1 -1
- package/dist/src/utils/inputBinding.js +26 -2
- 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 +6 -6
- package/dist/src/view/gridView.d.ts.map +1 -1
- package/dist/src/view/gridView.js +48 -29
- 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/unitView.d.ts +3 -14
- package/dist/src/view/unitView.d.ts.map +1 -1
- package/dist/src/view/unitView.js +26 -8
- package/dist/src/view/view.d.ts +14 -5
- package/dist/src/view/view.d.ts.map +1 -1
- package/dist/src/view/view.js +26 -7
- package/dist/src/view/zoom.d.ts +4 -10
- package/dist/src/view/zoom.d.ts.map +1 -1
- package/dist/src/view/zoom.js +126 -9
- package/package.json +2 -2
- package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.d.ts +0 -60
- package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.d.ts.map +0 -1
- package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.js +0 -128
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { lerp } from "vega-util";
|
|
2
|
+
import { makeLerpSmoother } from "./animator.js";
|
|
3
|
+
import clamp from "./clamp.js";
|
|
2
4
|
|
|
3
5
|
/**
|
|
4
6
|
* Creates some inertia, mainly for zooming with a mechanical mouse wheel
|
|
@@ -11,35 +13,32 @@ export default class Inertia {
|
|
|
11
13
|
constructor(animator, disabled) {
|
|
12
14
|
this.animator = animator;
|
|
13
15
|
this.disabled = !!disabled;
|
|
14
|
-
this.damping = 0.015;
|
|
15
|
-
this.acceleration = 0.3; // per event
|
|
16
|
-
/** Use acceleration if the momentum step is greater than X */
|
|
17
|
-
this.accelerationThreshold = 100;
|
|
18
|
-
this.lowerLimit = 0.5; // When to stop updating
|
|
19
|
-
this.loop = false;
|
|
20
16
|
|
|
21
|
-
|
|
22
|
-
this.
|
|
17
|
+
// Limit the velocity by setting the maximum distance the value can travel
|
|
18
|
+
this.maxDistance = 500;
|
|
19
|
+
|
|
23
20
|
/** @type {function(number):void} */
|
|
24
21
|
this.callback = null;
|
|
25
22
|
|
|
26
|
-
this.
|
|
27
|
-
this.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
23
|
+
this.targetValue = 0;
|
|
24
|
+
this.lastValue = 0;
|
|
25
|
+
|
|
26
|
+
this.smoother = makeLerpSmoother(
|
|
27
|
+
animator,
|
|
28
|
+
(value) => {
|
|
29
|
+
const delta = value - this.lastValue;
|
|
30
|
+
this.lastValue = value;
|
|
31
|
+
this.callback?.(delta);
|
|
32
|
+
},
|
|
33
|
+
40,
|
|
34
|
+
0.1
|
|
35
|
+
);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
cancel() {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
39
|
+
// decelelerate rapidly
|
|
40
|
+
this.targetValue = lerp([this.lastValue, this.targetValue], 0.3);
|
|
41
|
+
this.smoother(this.targetValue);
|
|
43
42
|
}
|
|
44
43
|
|
|
45
44
|
/**
|
|
@@ -53,50 +52,16 @@ export default class Inertia {
|
|
|
53
52
|
return;
|
|
54
53
|
}
|
|
55
54
|
|
|
56
|
-
// This may have some use in the future to improve the behavior of
|
|
57
|
-
// a mechanical mouse wheel:
|
|
58
|
-
// https://github.com/w3c/uievents/issues/181
|
|
59
|
-
|
|
60
|
-
if (value * this.momentum < 0) {
|
|
61
|
-
this.momentum = 0; // Stop if the direction changes
|
|
62
|
-
} else if (Math.abs(value) > this.accelerationThreshold) {
|
|
63
|
-
this.momentum = lerp([this.momentum, value], this.acceleration);
|
|
64
|
-
} else {
|
|
65
|
-
this.momentum = value;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
55
|
this.callback = callback;
|
|
69
56
|
|
|
70
|
-
|
|
71
|
-
this.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
*
|
|
77
|
-
* @param {number} [timestamp]
|
|
78
|
-
*/
|
|
79
|
-
animate(timestamp) {
|
|
80
|
-
this.callback(this.momentum); // TODO: This is actually a delta, should take the elapsed time into account
|
|
57
|
+
const delta = clamp(
|
|
58
|
+
this.targetValue + value - this.lastValue,
|
|
59
|
+
-this.maxDistance,
|
|
60
|
+
this.maxDistance
|
|
61
|
+
);
|
|
62
|
+
this.targetValue = this.lastValue + delta;
|
|
81
63
|
|
|
82
|
-
|
|
83
|
-
this.timestamp = timestamp;
|
|
84
|
-
|
|
85
|
-
const velocity = Math.abs(this.momentum);
|
|
86
|
-
|
|
87
|
-
this.momentum =
|
|
88
|
-
Math.sign(this.momentum) *
|
|
89
|
-
Math.max(
|
|
90
|
-
0,
|
|
91
|
-
velocity - ((velocity * this.damping) ** 1.5 + 0.04) * timeDelta
|
|
92
|
-
);
|
|
93
|
-
|
|
94
|
-
if (Math.abs(this.momentum) > this.lowerLimit) {
|
|
95
|
-
this.loop = true;
|
|
96
|
-
this.animator.requestTransition(this._transitionCallback);
|
|
97
|
-
} else {
|
|
98
|
-
this.clear();
|
|
99
|
-
}
|
|
64
|
+
this.smoother(this.targetValue);
|
|
100
65
|
}
|
|
101
66
|
}
|
|
102
67
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inputBinding.d.ts","sourceRoot":"","sources":["../../../src/utils/inputBinding.js"],"names":[],"mappings":"AAIA;;GAEG;AACH,sDAFW,OAAO,0BAA0B,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"inputBinding.d.ts","sourceRoot":"","sources":["../../../src/utils/inputBinding.js"],"names":[],"mappings":"AAIA;;GAEG;AACH,sDAFW,OAAO,0BAA0B,EAAE,OAAO,8CAqIpD"}
|
|
@@ -32,7 +32,6 @@ export default function createBindingInputs(mediator) {
|
|
|
32
32
|
const id = `${random}-param-${name}`;
|
|
33
33
|
|
|
34
34
|
if (bind.input == "range") {
|
|
35
|
-
// TODO: Show the value next to the slider
|
|
36
35
|
inputs.push(
|
|
37
36
|
html`<label for=${id}>${label}</label>
|
|
38
37
|
<div>
|
|
@@ -99,8 +98,33 @@ export default function createBindingInputs(mediator) {
|
|
|
99
98
|
)}
|
|
100
99
|
</select> `
|
|
101
100
|
);
|
|
101
|
+
} else if (
|
|
102
|
+
bind.input == "text" ||
|
|
103
|
+
bind.input == "number" ||
|
|
104
|
+
bind.input == "color"
|
|
105
|
+
) {
|
|
106
|
+
inputs.push(
|
|
107
|
+
html`<label for=${id}>${label}</label>
|
|
108
|
+
<div>
|
|
109
|
+
<input
|
|
110
|
+
id=${id}
|
|
111
|
+
type=${bind.input}
|
|
112
|
+
placeholder=${bind.placeholder ?? ""}
|
|
113
|
+
autocomplete=${bind.autocomplete ?? "off"}
|
|
114
|
+
.value=${value}
|
|
115
|
+
@focus=${(/** @type {any} */ e) =>
|
|
116
|
+
e.target.select()}
|
|
117
|
+
@input=${(/** @type {any} */ e) => {
|
|
118
|
+
debouncedSetter(
|
|
119
|
+
bind.input == "number"
|
|
120
|
+
? e.target.valueAsNumber
|
|
121
|
+
: e.target.value
|
|
122
|
+
);
|
|
123
|
+
}}
|
|
124
|
+
/>
|
|
125
|
+
</div>`
|
|
126
|
+
);
|
|
102
127
|
} else {
|
|
103
|
-
// TODO: Support other types: "text", "number", "color".
|
|
104
128
|
throw new Error("Unsupported input type: " + bind.input);
|
|
105
129
|
}
|
|
106
130
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template T
|
|
3
|
+
*/
|
|
4
|
+
export default class RingBuffer<T> {
|
|
5
|
+
/**
|
|
6
|
+
* @param {number} size
|
|
7
|
+
*/
|
|
8
|
+
constructor(size: number);
|
|
9
|
+
/** @param {T} value */
|
|
10
|
+
push(value: T): void;
|
|
11
|
+
/**
|
|
12
|
+
* @returns {T[]}
|
|
13
|
+
*/
|
|
14
|
+
get(): T[];
|
|
15
|
+
get size(): number;
|
|
16
|
+
get length(): number;
|
|
17
|
+
#private;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=ringBuffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ringBuffer.d.ts","sourceRoot":"","sources":["../../../src/utils/ringBuffer.js"],"names":[],"mappings":"AAAA;;GAEG;AACH;IAQI;;OAEG;IACH,kBAFW,MAAM,EAIhB;IAED,uBAAuB;IACvB,YADY,CAAC,QAKZ;IAED;;OAEG;IACH,OAFa,CAAC,EAAE,CAOf;IAED,mBAEC;IAED,qBAEC;;CACJ"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @template T
|
|
3
|
+
*/
|
|
4
|
+
export default class RingBuffer {
|
|
5
|
+
/** @type {T[]} */
|
|
6
|
+
#buffer;
|
|
7
|
+
|
|
8
|
+
#index = 0;
|
|
9
|
+
|
|
10
|
+
#length = 0;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @param {number} size
|
|
14
|
+
*/
|
|
15
|
+
constructor(size) {
|
|
16
|
+
this.#buffer = new Array(size);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** @param {T} value */
|
|
20
|
+
push(value) {
|
|
21
|
+
this.#buffer[this.#index] = value;
|
|
22
|
+
this.#index = (this.#index + 1) % this.size;
|
|
23
|
+
this.#length = Math.min(this.#length + 1, this.size);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @returns {T[]}
|
|
28
|
+
*/
|
|
29
|
+
get() {
|
|
30
|
+
const b = this.#buffer;
|
|
31
|
+
return this.#length < this.size
|
|
32
|
+
? b.slice(0, this.#length)
|
|
33
|
+
: b.slice(this.#index, this.size).concat(b.slice(0, this.#index));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
get size() {
|
|
37
|
+
return this.#buffer.length;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get length() {
|
|
41
|
+
return this.#length;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import RingBuffer from "./ringBuffer.js";
|
|
3
|
+
|
|
4
|
+
describe("ringBuffer", () => {
|
|
5
|
+
test("Empty buffer", () => {
|
|
6
|
+
const buffer = new RingBuffer(10);
|
|
7
|
+
expect(buffer.length).toBe(0);
|
|
8
|
+
expect(buffer.get()).toEqual([]);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("Partially filled buffer", () => {
|
|
12
|
+
const buffer = new RingBuffer(10);
|
|
13
|
+
buffer.push(1);
|
|
14
|
+
buffer.push(2);
|
|
15
|
+
buffer.push(3);
|
|
16
|
+
expect(buffer.length).toBe(3);
|
|
17
|
+
expect(buffer.get()).toEqual([1, 2, 3]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test("Full buffer", () => {
|
|
21
|
+
const buffer = new RingBuffer(3);
|
|
22
|
+
buffer.push(1);
|
|
23
|
+
buffer.push(2);
|
|
24
|
+
buffer.push(3);
|
|
25
|
+
expect(buffer.length).toBe(3);
|
|
26
|
+
expect(buffer.get()).toEqual([1, 2, 3]);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("Overfilled buffer", () => {
|
|
30
|
+
const buffer = new RingBuffer(3);
|
|
31
|
+
buffer.push(1);
|
|
32
|
+
buffer.push(2);
|
|
33
|
+
buffer.push(3);
|
|
34
|
+
buffer.push(4);
|
|
35
|
+
buffer.push(5);
|
|
36
|
+
expect(buffer.length).toBe(3);
|
|
37
|
+
expect(buffer.get()).toEqual([3, 4, 5]);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -117,22 +117,22 @@ declare class Scrollbar extends UnitView {
|
|
|
117
117
|
* @param {ScrollDirection} scrollDirection
|
|
118
118
|
*/
|
|
119
119
|
constructor(gridChild: GridChild, scrollDirection: "vertical" | "horizontal");
|
|
120
|
+
viewportOffset: number;
|
|
120
121
|
config: {
|
|
121
122
|
scrollbarSize: number;
|
|
122
123
|
scrollbarPadding: number;
|
|
123
124
|
};
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
getScrollOffset(): number;
|
|
125
|
+
interpolateViewportOffset: ((target: number) => void) & {
|
|
126
|
+
stop: () => void;
|
|
127
|
+
};
|
|
128
|
+
get scrollOffset(): number;
|
|
129
129
|
/**
|
|
130
130
|
*
|
|
131
131
|
* @param {Rectangle} viewportCoords
|
|
132
132
|
* @param {Rectangle} coords
|
|
133
133
|
*/
|
|
134
134
|
updateScrollbar(viewportCoords: Rectangle, coords: Rectangle): void;
|
|
135
|
-
|
|
135
|
+
#private;
|
|
136
136
|
}
|
|
137
137
|
import Padding from "./layout/padding.js";
|
|
138
138
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gridView.d.ts","sourceRoot":"","sources":["../../../src/view/gridView.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gridView.d.ts","sourceRoot":"","sources":["../../../src/view/gridView.js"],"names":[],"mappings":"AAswBA;;;GAGG;AACH,iDAHW,OAAO,iBAAiB,EAAE,cAAc,GACtC,OAAO,iBAAiB,EAAE,QAAQ,CAwB9C;AAED;;;GAGG;AACH,uDAHW,OAAO,iBAAiB,EAAE,cAAc,GACtC,OAAO,iBAAiB,EAAE,QAAQ,CA6C9C;AA2BD;;GAEG;AACH,8EAUC;AAED;;;;;GAKG;AACH,4CAJW,OAAO,uBAAuB,EAAE,OAAO,UACvC,OAAO,iBAAiB,EAAE,UAAU,YACpC,QAAQ,aAmBlB;AA53BD;;;;;;;;;;;;;;;GAeG;AACH;IA6BI;;;;;;;;;OASG;IACH,kBARW,OAAO,iBAAiB,EAAE,aAAa,WACvC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,aAAa,iDAEb,MAAM,WACN,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EAoBzC;IARG,8CAAgB;IAOhB,uBAA0B;IAG9B;;OAEG;IACH,qDAIC;IAeD;;OAEG;IACH,wDAKC;IAqBD;;OAEG;IACH,8CAEC;IAED,yBAEC;IAED;;OAEG;IACH,wCAmCC;IA2OD;;;;OAIG;IAEH,gBALW,OAAO,4CAA4C,EAAE,OAAO,UAC5D,OAAO,uBAAuB,EAAE,OAAO,YACvC,OAAO,uBAAuB,EAAE,gBAAgB,QA6O1D;;CAoGJ;AAgJD;IACI;;;;OAIG;IACH,6DAHW,aAAa,UACb,MAAM,EAoFhB;IAjFG,4BAAgC;IAChC,kCAAgB;IAChB,eAAoB;IAEpB,uBAAuB;IACvB,YADW,QAAQ,CACQ;IAE3B,uBAAuB;IACvB,kBADW,QAAQ,CACc;IAEjC,mFAAmF;IACnF,MADW,QAAQ,OAAO,OAAO,iBAAiB,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC,CAC5D;IAEd,4FAA4F;IAC5F,WADW,QAAQ,OAAO,OAAO,iBAAiB,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAC3D;IAEnB,0DAA0D;IAC1D,kEAAoB;IAEpB,uBAAuB;IACvB,OADW,QAAQ,CACG;IAEtB,wBAAwB;IACxB,QADW,SAAS,CACQ;IA4DhC,uEAcC;IAED;;OAEG;IACH,4BAkKC;IAED,uBAqBC;IAED,iCAEC;CACJ;qBAlrC0D,eAAe;sBAFpD,uBAAuB;0BAGnB,oBAAoB;qBAGzB,eAAe;yBALX,mBAAmB;AAqrC5C;IAeI;;;OAGG;IACH,uBAHW,SAAS,8CA4FnB;IA/FD,uBAAmB;IAsCf;;;MAAoB;IAIpB;;MAQC;IA+CL,2BAKC;IAWD;;;;OAIG;IACH,gCAHW,SAAS,UACT,SAAS,QA8CnB;;CACJ;oBAv2CmB,qBAAqB"}
|
|
@@ -16,8 +16,9 @@ import ContainerView from "./containerView.js";
|
|
|
16
16
|
import LayerView from "./layerView.js";
|
|
17
17
|
import createTitle from "./title.js";
|
|
18
18
|
import UnitView from "./unitView.js";
|
|
19
|
-
import interactionToZoom from "./zoom.js";
|
|
19
|
+
import { interactionToZoom } from "./zoom.js";
|
|
20
20
|
import clamp from "../utils/clamp.js";
|
|
21
|
+
import { makeLerpSmoother } from "../utils/animator.js";
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Modeled after: https://vega.github.io/vega/docs/layout/
|
|
@@ -711,7 +712,8 @@ export default class GridView extends ContainerView {
|
|
|
711
712
|
pointedChild.view,
|
|
712
713
|
zoomEvent
|
|
713
714
|
),
|
|
714
|
-
this.context.getCurrentHover()
|
|
715
|
+
this.context.getCurrentHover(),
|
|
716
|
+
this.context.animator
|
|
715
717
|
);
|
|
716
718
|
}
|
|
717
719
|
}
|
|
@@ -1214,6 +1216,20 @@ export class GridChild {
|
|
|
1214
1216
|
}
|
|
1215
1217
|
|
|
1216
1218
|
class Scrollbar extends UnitView {
|
|
1219
|
+
/** @type {ScrollDirection} */
|
|
1220
|
+
#scrollDirection;
|
|
1221
|
+
|
|
1222
|
+
#scrollbarCoords = Rectangle.ZERO;
|
|
1223
|
+
|
|
1224
|
+
#maxScrollOffset = 0;
|
|
1225
|
+
|
|
1226
|
+
#maxViewportOffset = 0;
|
|
1227
|
+
|
|
1228
|
+
// This is the actual state of the scrollbar. It's better to keep track of
|
|
1229
|
+
// the viewport offset rather than the scrollbar offset because the former
|
|
1230
|
+
// is more stable when the viewport size changes.
|
|
1231
|
+
viewportOffset = 0;
|
|
1232
|
+
|
|
1217
1233
|
/**
|
|
1218
1234
|
* @param {GridChild} gridChild
|
|
1219
1235
|
* @param {ScrollDirection} scrollDirection
|
|
@@ -1251,20 +1267,23 @@ class Scrollbar extends UnitView {
|
|
|
1251
1267
|
);
|
|
1252
1268
|
|
|
1253
1269
|
this.config = config;
|
|
1254
|
-
this
|
|
1270
|
+
this.#scrollDirection = scrollDirection;
|
|
1255
1271
|
|
|
1256
|
-
//
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1272
|
+
// Make it smooth!
|
|
1273
|
+
this.interpolateViewportOffset = makeLerpSmoother(
|
|
1274
|
+
this.context.animator,
|
|
1275
|
+
(value) => {
|
|
1276
|
+
this.viewportOffset = value;
|
|
1277
|
+
},
|
|
1278
|
+
50,
|
|
1279
|
+
0.4,
|
|
1280
|
+
this.viewportOffset
|
|
1281
|
+
);
|
|
1263
1282
|
|
|
1264
1283
|
this.addInteractionEventListener("mousedown", (coords, event) => {
|
|
1265
1284
|
event.stopPropagation();
|
|
1266
1285
|
|
|
1267
|
-
if (this
|
|
1286
|
+
if (this.#maxScrollOffset <= 0) {
|
|
1268
1287
|
return;
|
|
1269
1288
|
}
|
|
1270
1289
|
|
|
@@ -1276,7 +1295,7 @@ class Scrollbar extends UnitView {
|
|
|
1276
1295
|
const mouseEvent = /** @type {MouseEvent} */ (event.uiEvent);
|
|
1277
1296
|
mouseEvent.preventDefault();
|
|
1278
1297
|
|
|
1279
|
-
const initialScrollOffset = this.
|
|
1298
|
+
const initialScrollOffset = this.scrollOffset;
|
|
1280
1299
|
const initialOffset = getMouseOffset(mouseEvent);
|
|
1281
1300
|
|
|
1282
1301
|
const onMousemove = /** @param {MouseEvent} moveEvent */ (
|
|
@@ -1287,13 +1306,13 @@ class Scrollbar extends UnitView {
|
|
|
1287
1306
|
initialOffset +
|
|
1288
1307
|
initialScrollOffset,
|
|
1289
1308
|
0,
|
|
1290
|
-
this
|
|
1309
|
+
this.#maxScrollOffset
|
|
1291
1310
|
);
|
|
1292
1311
|
|
|
1293
|
-
this.
|
|
1294
|
-
(scrollOffset / this
|
|
1295
|
-
|
|
1296
|
-
|
|
1312
|
+
this.interpolateViewportOffset(
|
|
1313
|
+
(scrollOffset / this.#maxScrollOffset) *
|
|
1314
|
+
this.#maxViewportOffset
|
|
1315
|
+
);
|
|
1297
1316
|
};
|
|
1298
1317
|
|
|
1299
1318
|
const onMouseup = () => {
|
|
@@ -1306,10 +1325,10 @@ class Scrollbar extends UnitView {
|
|
|
1306
1325
|
});
|
|
1307
1326
|
}
|
|
1308
1327
|
|
|
1309
|
-
|
|
1328
|
+
get scrollOffset() {
|
|
1310
1329
|
return (
|
|
1311
|
-
(this.viewportOffset / this
|
|
1312
|
-
this
|
|
1330
|
+
(this.viewportOffset / this.#maxViewportOffset) *
|
|
1331
|
+
this.#maxScrollOffset
|
|
1313
1332
|
);
|
|
1314
1333
|
}
|
|
1315
1334
|
|
|
@@ -1319,7 +1338,7 @@ class Scrollbar extends UnitView {
|
|
|
1319
1338
|
* @param {import("../types/rendering.js").RenderingOptions} [options]
|
|
1320
1339
|
*/
|
|
1321
1340
|
render(context, coords, options) {
|
|
1322
|
-
super.render(context, this
|
|
1341
|
+
super.render(context, this.#scrollbarCoords, options);
|
|
1323
1342
|
}
|
|
1324
1343
|
|
|
1325
1344
|
/**
|
|
@@ -1332,7 +1351,7 @@ class Scrollbar extends UnitView {
|
|
|
1332
1351
|
const sSize = this.config.scrollbarSize;
|
|
1333
1352
|
|
|
1334
1353
|
const dimension =
|
|
1335
|
-
this
|
|
1354
|
+
this.#scrollDirection == "horizontal" ? "width" : "height";
|
|
1336
1355
|
|
|
1337
1356
|
const visibleFraction = Math.min(
|
|
1338
1357
|
1,
|
|
@@ -1341,28 +1360,28 @@ class Scrollbar extends UnitView {
|
|
|
1341
1360
|
const maxScrollLength = viewportCoords[dimension] - 2 * sPad;
|
|
1342
1361
|
const scrollLength = visibleFraction * maxScrollLength;
|
|
1343
1362
|
|
|
1344
|
-
this
|
|
1345
|
-
this
|
|
1363
|
+
this.#maxScrollOffset = maxScrollLength - scrollLength;
|
|
1364
|
+
this.#maxViewportOffset = coords[dimension] - viewportCoords[dimension];
|
|
1346
1365
|
this.viewportOffset = clamp(
|
|
1347
1366
|
this.viewportOffset,
|
|
1348
1367
|
0,
|
|
1349
|
-
this
|
|
1368
|
+
this.#maxViewportOffset
|
|
1350
1369
|
);
|
|
1351
1370
|
|
|
1352
|
-
this
|
|
1353
|
-
this
|
|
1371
|
+
this.#scrollbarCoords =
|
|
1372
|
+
this.#scrollDirection == "vertical"
|
|
1354
1373
|
? new Rectangle(
|
|
1355
1374
|
() =>
|
|
1356
1375
|
viewportCoords.x +
|
|
1357
1376
|
viewportCoords.width -
|
|
1358
1377
|
sSize -
|
|
1359
1378
|
sPad,
|
|
1360
|
-
() => viewportCoords.y + sPad + this.
|
|
1379
|
+
() => viewportCoords.y + sPad + this.scrollOffset,
|
|
1361
1380
|
() => sSize,
|
|
1362
1381
|
() => scrollLength
|
|
1363
1382
|
)
|
|
1364
1383
|
: new Rectangle(
|
|
1365
|
-
() => viewportCoords.x + sPad + this.
|
|
1384
|
+
() => viewportCoords.x + sPad + this.scrollOffset,
|
|
1366
1385
|
() =>
|
|
1367
1386
|
viewportCoords.y +
|
|
1368
1387
|
viewportCoords.height -
|
|
@@ -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) {
|
|
@@ -6,15 +6,7 @@
|
|
|
6
6
|
export const markTypes: {
|
|
7
7
|
[x: string]: typeof import("../marks/mark.js").default;
|
|
8
8
|
};
|
|
9
|
-
export default class UnitView extends
|
|
10
|
-
/**
|
|
11
|
-
* @typedef {import("../spec/channel.js").Channel} Channel
|
|
12
|
-
* @typedef {import("./view.js").default} View
|
|
13
|
-
* @typedef {import("./layerView.js").default} LayerView
|
|
14
|
-
* @typedef {import("../utils/domainArray.js").DomainArray} DomainArray
|
|
15
|
-
* @typedef {import("../spec/view.js").ResolutionTarget} ResolutionTarget
|
|
16
|
-
*
|
|
17
|
-
*/
|
|
9
|
+
export default class UnitView extends View {
|
|
18
10
|
/**
|
|
19
11
|
*
|
|
20
12
|
* @param {import("../spec/view.js").UnitSpec} spec
|
|
@@ -51,10 +43,6 @@ export default class UnitView extends ContainerView {
|
|
|
51
43
|
* Returns a collector that is associated with this view.
|
|
52
44
|
*/
|
|
53
45
|
getCollector(): import("../data/collector.js").default;
|
|
54
|
-
/**
|
|
55
|
-
* @param {Channel} channel A primary channel
|
|
56
|
-
*/
|
|
57
|
-
_validateDomainQuery(channel: import("../spec/channel.js").Channel): import("../spec/channel.js").MarkPropExprDef<import("../spec/channel.js").Type> | import("../spec/channel.js").MarkPropDatumDef<import("../spec/channel.js").Type> | import("../spec/channel.js").ChromPosDef | import("../spec/channel.js").PositionDatumDef | (import("../spec/channel.js").ChromPosDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").TypeMixins<"locus"> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").XIndexDef) | (import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").DatumDefBase & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | import("../spec/channel.js").MarkPropDatumDef<import("../spec/channel.js").TypeForShape> | import("../spec/channel.js").MarkPropFieldDef<string, import("../spec/channel.js").Type> | import("../spec/channel.js").PositionFieldDef<string> | (import("../spec/channel.js").FieldDefBase<string> & import("../spec/channel.js").TitleMixins & import("../spec/channel.js").TypeMixins<import("../spec/channel.js").Type> & import("../spec/channel.js").ScaleMixins & import("../spec/channel.js").PositionMixins & import("../spec/channel.js").XIndexDef) | import("../spec/channel.js").MarkPropFieldDef<string, import("../spec/channel.js").TypeForShape>;
|
|
58
46
|
/**
|
|
59
47
|
* Returns the domain of the specified channel of this domain/mark.
|
|
60
48
|
*
|
|
@@ -83,6 +71,7 @@ export default class UnitView extends ContainerView {
|
|
|
83
71
|
* @returns {import("../spec/view.js").ResolutionBehavior}
|
|
84
72
|
*/
|
|
85
73
|
getDefaultResolution(channel: string, resolutionType: import("../spec/view.js").ResolutionTarget): import("../spec/view.js").ResolutionBehavior;
|
|
74
|
+
#private;
|
|
86
75
|
}
|
|
87
|
-
import
|
|
76
|
+
import View from "./view.js";
|
|
88
77
|
//# sourceMappingURL=unitView.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"AAqBA;;;;GAIG;AACH;QAHkB,MAAM,GAAE,cAAc,kBAAkB,EAAE,OAAO;EASjE;AAEF;
|
|
1
|
+
{"version":3,"file":"unitView.d.ts","sourceRoot":"","sources":["../../../src/view/unitView.js"],"names":[],"mappings":"AAqBA;;;;GAIG;AACH;QAHkB,MAAM,GAAE,cAAc,kBAAkB,EAAE,OAAO;EASjE;AAEF;IAcI;;;;;;;;OAQG;IACH,kBAPW,OAAO,iBAAiB,EAAE,QAAQ,WAClC,OAAO,yBAAyB,EAAE,OAAO,gBACzC,OAAO,oBAAoB,EAAE,OAAO,cACpC,OAAO,WAAW,EAAE,OAAO,QAC3B,MAAM,YACN,OAAO,WAAW,EAAE,WAAW,EA+BzC;IA1BG,yCAAgB;IAIZ,iDAAiD;IACjD,MADW,OAAO,kBAAkB,EAAE,OAAO,CACnB;IAuBlC;;;;OAIG;IACH,gBAJW,OAAO,4CAA4C,EAAE,OAAO,UAC5D,OAAO,uBAAuB,EAAE,OAAO,YACvC,OAAO,uBAAuB,EAAE,gBAAgB,QAY1D;IAED,kDAIC;IAED;;;;;OAKG;IACH,iEAgFC;IAED;;;OAGG;IACH,mGASC;IAkBD;;OAEG;IACH,uDAEC;IAqBD;;;;;OAKG;IACH,6BAHW,OAAO,oBAAoB,EAAE,gBAAgB,iDAkBvD;IAED;;;;;;;;;;;;OAYG;IACH,gHA2CC;IAED,uBAQC;IAgBD;;;;OAIG;IACH,8BAJW,MAAM,+DAEJ,OAAO,iBAAiB,EAAE,kBAAkB,CAKxD;;CACJ;iBA/VgB,WAAW"}
|