@genome-spy/core 0.46.0 → 0.47.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 +5429 -5306
- package/dist/bundle/index.js +104 -93
- package/dist/schema.json +38 -0
- package/dist/src/data/flowNode.d.ts +22 -7
- package/dist/src/data/flowNode.d.ts.map +1 -1
- package/dist/src/data/flowNode.js +29 -6
- package/dist/src/data/flowTestUtils.d.ts +5 -0
- package/dist/src/data/flowTestUtils.d.ts.map +1 -1
- package/dist/src/data/flowTestUtils.js +11 -0
- package/dist/src/data/transforms/clone.d.ts +1 -0
- package/dist/src/data/transforms/clone.d.ts.map +1 -1
- package/dist/src/data/transforms/coverage.d.ts +4 -1
- package/dist/src/data/transforms/coverage.d.ts.map +1 -1
- package/dist/src/data/transforms/coverage.js +44 -31
- package/dist/src/data/transforms/filter.d.ts +2 -1
- package/dist/src/data/transforms/filter.d.ts.map +1 -1
- package/dist/src/data/transforms/filter.js +4 -2
- package/dist/src/data/transforms/filter.test.js +2 -6
- package/dist/src/data/transforms/formula.d.ts +2 -1
- package/dist/src/data/transforms/formula.d.ts.map +1 -1
- package/dist/src/data/transforms/formula.js +4 -2
- package/dist/src/data/transforms/formula.test.js +9 -9
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +23 -15
- 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 +15 -0
- package/dist/src/utils/animator.d.ts.map +1 -1
- package/dist/src/utils/animator.js +66 -0
- package/dist/src/utils/inertia.d.ts +4 -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/view/gridView.d.ts +4 -6
- package/dist/src/view/gridView.d.ts.map +1 -1
- package/dist/src/view/gridView.js +45 -27
- 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 +2 -2
- package/dist/src/view/zoom.d.ts.map +1 -1
- package/dist/src/view/zoom.js +1 -1
- 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
|
@@ -25,11 +25,12 @@ export default class WebGLHelper {
|
|
|
25
25
|
* A function that returns the content size. If a dimension is undefined,
|
|
26
26
|
* the canvas fills the container, otherwise the canvas is adjusted to the content size.
|
|
27
27
|
* @param {string} [clearColor]
|
|
28
|
+
* @param {WebGLContextAttributes} [webglContextAttributes]
|
|
28
29
|
*/
|
|
29
30
|
constructor(container: HTMLElement, sizeSource?: () => {
|
|
30
31
|
width: number;
|
|
31
32
|
height: number;
|
|
32
|
-
}, clearColor?: string);
|
|
33
|
+
}, clearColor?: string, webglContextAttributes?: WebGLContextAttributes);
|
|
33
34
|
_container: HTMLElement;
|
|
34
35
|
_sizeSource: () => {
|
|
35
36
|
width: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webGLHelper.d.ts","sourceRoot":"","sources":["../../../src/gl/webGLHelper.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"webGLHelper.d.ts","sourceRoot":"","sources":["../../../src/gl/webGLHelper.js"],"names":[],"mappings":"AAmaA;;;;GAIG;AACH,kCAJW,sBAAsB,gBACtB,WAAW,kBACX,WAAW;;;;;;EA8CrB;AAED;;;;;GAKG;AACH,0CALW,qBAAqB,WACrB,KAAK,OAAO,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC,OAC7C,MAAM,EAAE,GAAG,eAAe,YAC1B,YAAY,gBAYtB;AAxcD;IACI;;;;;;;;OAQG;IACH,uBAPW,WAAW,eACX,MAAM;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,eAGrC,MAAM,2BACN,sBAAsB,EAyFhC;IAjFG,wBAA2B;IAC3B;;;MAKO;IAEP,uCAAuC;IACvC,cADW,IAAI,MAAM,EAAE,WAAW,CAAC,CACN;IAE7B,kFAAkF;IAClF,eADW,QAAQ,OAAO,4BAA4B,EAAE,OAAO,EAAE,YAAY,CAAC,CAC5C;IAwClC,0BAAoB;IACpB,2BAAY;IAGZ,oDAAoD;IACpD,2BADW,OAAO,SAAS,EAAE,iBAAiB,EAAE,CAQ/C;IACD,sDAGC;IAOD,+CAA+C;IAC/C,aADW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CACZ;IAOnC,uBAIC;IAHG;;;MAAmC;IAKvC,mBAEC;IADG,YAAkC;IAGtC;;;;;OAKG;IACH,oBAHW,MAAM,QACN,MAAM,GAAG,MAAM,EAAE,eA2B3B;IAED,iBAcC;IAED,iBAEC;IAED;;;;OAIG;IACH,oCAFW;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE;;;MAQ3C;IAED;;OAEG;IACH;;;MAuBC;IAED;;;;OAIG;IACH,oBAHW,MAAM,KACN,MAAM,cAwBhB;IAED,iBAOC;IAED;;;;;;;;;OASG;IACH,+BAHW,OAAO,4BAA4B,EAAE,OAAO,WAC5C,OAAO,QA0GjB;CACJ"}
|
|
@@ -36,8 +36,14 @@ export default class WebGLHelper {
|
|
|
36
36
|
* A function that returns the content size. If a dimension is undefined,
|
|
37
37
|
* the canvas fills the container, otherwise the canvas is adjusted to the content size.
|
|
38
38
|
* @param {string} [clearColor]
|
|
39
|
+
* @param {WebGLContextAttributes} [webglContextAttributes]
|
|
39
40
|
*/
|
|
40
|
-
constructor(
|
|
41
|
+
constructor(
|
|
42
|
+
container,
|
|
43
|
+
sizeSource,
|
|
44
|
+
clearColor,
|
|
45
|
+
webglContextAttributes = {}
|
|
46
|
+
) {
|
|
41
47
|
this._container = container;
|
|
42
48
|
this._sizeSource =
|
|
43
49
|
sizeSource ??
|
|
@@ -67,6 +73,7 @@ export default class WebGLHelper {
|
|
|
67
73
|
// Disable depth writes. We don't use depth testing.
|
|
68
74
|
depth: false,
|
|
69
75
|
premultipliedAlpha: true,
|
|
76
|
+
...webglContextAttributes,
|
|
70
77
|
})
|
|
71
78
|
);
|
|
72
79
|
|
package/dist/src/marks/mark.d.ts
CHANGED
|
@@ -22,27 +22,39 @@ export default class Mark {
|
|
|
22
22
|
unitView: import("../view/unitView.js").default;
|
|
23
23
|
/** @type {Record<string, import("../types/encoder.js").Encoder>} */
|
|
24
24
|
encoders: Record<string, import("../types/encoder.js").Encoder>;
|
|
25
|
-
/**
|
|
26
|
-
|
|
25
|
+
/**
|
|
26
|
+
* @type {import("twgl.js").BufferInfo & { allocatedVertices?: number }}
|
|
27
|
+
* @protected
|
|
28
|
+
*/
|
|
29
|
+
protected bufferInfo: import("twgl.js").BufferInfo & {
|
|
27
30
|
allocatedVertices?: number;
|
|
28
31
|
};
|
|
29
|
-
/**
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
/**
|
|
33
|
+
* @type {import("twgl.js").ProgramInfo}
|
|
34
|
+
* @protected
|
|
35
|
+
*/
|
|
36
|
+
protected programInfo: import("twgl.js").ProgramInfo;
|
|
37
|
+
/**
|
|
38
|
+
* @type {import("twgl.js").VertexArrayInfo}
|
|
39
|
+
* @protected
|
|
40
|
+
*/
|
|
41
|
+
protected vertexArrayInfo: import("twgl.js").VertexArrayInfo;
|
|
42
|
+
/**
|
|
43
|
+
* @type {import("twgl.js").UniformBlockInfo}
|
|
44
|
+
* @protected
|
|
45
|
+
*/
|
|
46
|
+
protected viewUniformInfo: import("twgl.js").UniformBlockInfo;
|
|
37
47
|
/**
|
|
38
48
|
* Uniforms related to the specific mark type.
|
|
49
|
+
*
|
|
39
50
|
* @type {import("twgl.js").UniformBlockInfo}
|
|
51
|
+
* @protected
|
|
40
52
|
*/
|
|
41
|
-
markUniformInfo: import("twgl.js").UniformBlockInfo;
|
|
53
|
+
protected markUniformInfo: import("twgl.js").UniformBlockInfo;
|
|
42
54
|
/**
|
|
43
55
|
* Indicates whether the mark's uniforms have been altered since the last rendering.
|
|
44
56
|
* If set to true, the uniforms will be sent to the GPU before rendering the next frame.
|
|
45
|
-
|
|
57
|
+
*
|
|
46
58
|
* @protected
|
|
47
59
|
*/
|
|
48
60
|
protected markUniformsAltered: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":";AA4CA,0DAA2D;AAC3D,0DAA2D;AAE3D;;;;;;;;;;;;GAYG;AACH;IAgBI;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,
|
|
1
|
+
{"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":";AA4CA,0DAA2D;AAC3D,0DAA2D;AAE3D;;;;;;;;;;;;GAYG;AACH;IAgBI;;OAEG;IACH,sBAFW,OAAO,qBAAqB,EAAE,OAAO,EA6F/C;IA1FG,gDAAwB;IAExB,oEAAoE;IACpE,UADW,OAAO,MAAM,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CACvC;IAIzB;;;OAGG;IACH,sBAHU,OAAO,SAAS,EAAE,UAAU,GAAG;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,CAG5C;IAE3B;;;OAGG;IACH,uBAHU,OAAO,SAAS,EAAE,WAAW,CAGX;IAE5B;;;OAGG;IACH,2BAHU,OAAO,SAAS,EAAE,eAAe,CAGX;IAEhC;;;OAGG;IACH,2BAHU,OAAO,SAAS,EAAE,gBAAgB,CAGZ;IAEhC;;;;;OAKG;IACH,2BAHU,OAAO,SAAS,EAAE,gBAAgB,CAGZ;IAEhC;;;;;OAKG;IACH,uCAA+B;IAE/B,kFAAkF;IAClF,UADW,SAAS,GAAG,CAAC,CACM;IAG9B,wBAAwB;IACxB,uDAqBC;IAED;;;;;;;;OAQG;IACH,kEAKC;IAGL,sBAEC;IAED;;;;;;;OAOG;IACH,iBAFa,MAAM,EAAE,CAKpB;IAED;;OAEG;IACH,+DAWC;IAED;;OAEG;IACH,oEAcC;IAED;;;;;OAKG;IACH,oHAEC;IAED;;;;;;OAMG;IACH,yGAkCC;IAED;;;;OAIG;IACH,8DAiDC;IAED,wDAEC;IAED,8CAEC;IAED,uBAEC;IAED;;;OAGG;IACH,2BAEC;IAED;;OAEG;IACH,oCAEC;IAED;;OAEG;IACH,2BAEC;IAED,sEAeC;IAED;;;;;;OAMG;IAEH,6CANW,MAAM,kBACN,MAAM,iBACN,MAAM,EAAE,QA8NlB;IALG;;;;;;MAIC;IAGL;;;;;;OAMG;IACH,uCA6CC;IAED;;;;;;OAMG;IACH,+CAHW,MAAM,UACK,GAAG,KAAE,IAAI,CAe9B;IAED;;;;;;;;;;OAUG;IACH,mDAJW,MAAM,sFAEsB,GAAG,QA6BzC;IAED;;OAEG;IACH,2BAwBC;IAED;;;OAGG;IACH,6BAFW,GAAG,QAgCb;IAED,yBAAyB;IACzB,uDAEC;IAED,yBAAyB;IACzB,iCAEC;IAED,gCAEC;IAED,+BAEC;IAED,yCAEC;IAED;;;;;OAKG;IACH,gCAcC;IAED;;OAEG;IACH,4CAOC;IAED;;;;;;;;OAQG;IAEH,uBAJW,OAAO,uBAAuB,EAAE,sBAAsB,GACpD,CAAC,MAAM,IAAI,CAAC,EAAE,CAsF1B;IAED;;;;;;OAMG;IACH,qCAJW,oBAAoB,GAClB,OAAO,CAqCnB;IAED;;;;;;;OAOG;IACH,gBAJW,oBAAoB,SACP,IAAI,CAM3B;IAED;;;OAGG;IACH,2BAHW,YAAY,WACZ,OAAO,WAAW,EAAE,oBAAoB,cAiElD;IAED;;;;;;OAMG;IACH,oBAJW,OAAO,6BAA6B,EAAE,OAAO,aAC7C,OAAO,6BAA6B,EAAE,OAAO,GAC3C,OAAO,CAuHnB;IAED;;;;;;;;;OASG;IACH,qBAJW,MAAM,KACN,OAAO,oBAAoB,EAAE,MAAM,GACjC,GAAG,CAIf;;CACJ;+BAvoCY,OAAO,uBAAuB,EAAE,gBAAgB;;;;;;wBAEnD,OAAO;;mCAEJ,gBAAgB,GAAG,qBAAqB;oCAG1C,MAAM,SACN,MAAM;AAioCjB;;;GAGG;AACH;IACI,cAEC;IAkBD;;;OAGG;IACH,2BAFW,IAAI,CAAC,EAAE,OAAO,yBAAyB,EAAE,UAAU,CAAC,QAiB9D;CACJ;0BA/rCyB,WAAW"}
|
package/dist/src/marks/mark.js
CHANGED
|
@@ -85,31 +85,42 @@ export default class Mark {
|
|
|
85
85
|
|
|
86
86
|
// TODO: Consolidate the following webgl stuff into a single object
|
|
87
87
|
|
|
88
|
-
/**
|
|
88
|
+
/**
|
|
89
|
+
* @type {import("twgl.js").BufferInfo & { allocatedVertices?: number }}
|
|
90
|
+
* @protected
|
|
91
|
+
*/
|
|
89
92
|
this.bufferInfo = undefined;
|
|
90
93
|
|
|
91
|
-
/**
|
|
94
|
+
/**
|
|
95
|
+
* @type {import("twgl.js").ProgramInfo}
|
|
96
|
+
* @protected
|
|
97
|
+
*/
|
|
92
98
|
this.programInfo = undefined;
|
|
93
99
|
|
|
94
|
-
/**
|
|
100
|
+
/**
|
|
101
|
+
* @type {import("twgl.js").VertexArrayInfo}
|
|
102
|
+
* @protected
|
|
103
|
+
*/
|
|
95
104
|
this.vertexArrayInfo = undefined;
|
|
96
105
|
|
|
97
|
-
/**
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
106
|
+
/**
|
|
107
|
+
* @type {import("twgl.js").UniformBlockInfo}
|
|
108
|
+
* @protected
|
|
109
|
+
*/
|
|
101
110
|
this.viewUniformInfo = undefined;
|
|
102
111
|
|
|
103
112
|
/**
|
|
104
113
|
* Uniforms related to the specific mark type.
|
|
114
|
+
*
|
|
105
115
|
* @type {import("twgl.js").UniformBlockInfo}
|
|
116
|
+
* @protected
|
|
106
117
|
*/
|
|
107
118
|
this.markUniformInfo = undefined;
|
|
108
119
|
|
|
109
120
|
/**
|
|
110
121
|
* Indicates whether the mark's uniforms have been altered since the last rendering.
|
|
111
122
|
* If set to true, the uniforms will be sent to the GPU before rendering the next frame.
|
|
112
|
-
|
|
123
|
+
*
|
|
113
124
|
* @protected
|
|
114
125
|
*/
|
|
115
126
|
this.markUniformsAltered = true;
|
|
@@ -719,8 +730,15 @@ export default class Mark {
|
|
|
719
730
|
* Delete WebGL buffers etc.
|
|
720
731
|
*/
|
|
721
732
|
deleteGraphicsData() {
|
|
733
|
+
const gl = this.gl;
|
|
734
|
+
|
|
735
|
+
if (this.vertexArrayInfo) {
|
|
736
|
+
this.gl.bindVertexArray(null);
|
|
737
|
+
gl.deleteVertexArray(this.vertexArrayInfo.vertexArrayObject);
|
|
738
|
+
this.vertexArrayInfo = undefined;
|
|
739
|
+
}
|
|
740
|
+
|
|
722
741
|
if (this.bufferInfo) {
|
|
723
|
-
const gl = this.gl;
|
|
724
742
|
// A hack to prevent WebGL: INVALID_OPERATION: drawArrays: no buffer is bound to enabled attribute
|
|
725
743
|
// TODO: Consider using bufferSubData or DYNAMIC_DRAW etc...
|
|
726
744
|
for (let i = 0; i < 8; i++) {
|
|
@@ -742,7 +760,6 @@ export default class Mark {
|
|
|
742
760
|
* @param {any} vertexData TODO: Extract type from VertexBuilder
|
|
743
761
|
*/
|
|
744
762
|
updateBufferInfo(vertexData) {
|
|
745
|
-
// Ensure that no VAOs are inadvertently altered
|
|
746
763
|
this.gl.bindVertexArray(null);
|
|
747
764
|
|
|
748
765
|
if (
|
|
@@ -761,8 +778,6 @@ export default class Mark {
|
|
|
761
778
|
attributeData.data,
|
|
762
779
|
0
|
|
763
780
|
);
|
|
764
|
-
// TODO: Consider double buffering:
|
|
765
|
-
// https://community.khronos.org/t/texture-buffers-are-much-slower-than-uniform-buffers/77139
|
|
766
781
|
}
|
|
767
782
|
}
|
|
768
783
|
} else {
|
|
@@ -773,7 +788,6 @@ export default class Mark {
|
|
|
773
788
|
{ numElements: vertexData.vertexCount }
|
|
774
789
|
);
|
|
775
790
|
this.bufferInfo.allocatedVertices = vertexData.allocatedVertices;
|
|
776
|
-
this.vertexArrayInfo = undefined;
|
|
777
791
|
}
|
|
778
792
|
}
|
|
779
793
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/marks/point.js"],"names":[],"mappings":"AAmBA;IA0HY,oCAMC;
|
|
1
|
+
{"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/marks/point.js"],"names":[],"mappings":"AAmBA;IA0HY,oCAMC;IA6DT,+BAkBC;;CAgDJ;iBAvQgB,WAAW"}
|
package/dist/src/marks/point.js
CHANGED
|
@@ -192,7 +192,11 @@ export default class PointMark extends Mark {
|
|
|
192
192
|
this.updateBufferInfo(vertexData);
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
|
|
195
|
+
/**
|
|
196
|
+
* This and `geometricZoomBound` should be deprecated once params (zoomLevel) and
|
|
197
|
+
* expressions are documented.
|
|
198
|
+
*/
|
|
199
|
+
#getGeometricScaleFactor() {
|
|
196
200
|
const zoomLevel = Math.pow(2, this.properties.geometricZoomBound || 0);
|
|
197
201
|
|
|
198
202
|
return Math.pow(
|
|
@@ -231,7 +235,7 @@ export default class PointMark extends Mark {
|
|
|
231
235
|
ops.push(() => {
|
|
232
236
|
// TODO: Use bindUniformBlock if none of the uniform has changed
|
|
233
237
|
setBlockUniforms(this.markUniformInfo, {
|
|
234
|
-
uScaleFactor: this
|
|
238
|
+
uScaleFactor: this.#getGeometricScaleFactor(),
|
|
235
239
|
uSemanticThreshold: this.getSemanticThreshold(),
|
|
236
240
|
});
|
|
237
241
|
this.markUniformsAltered = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/marks/text.js"],"names":[],"mappings":"AAgCA;;;;;;;GAOG;AACH;IAyDQ,oDAMmD;
|
|
1
|
+
{"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/marks/text.js"],"names":[],"mappings":"AAgCA;;;;;;;GAOG;AACH;IAyDQ,oDAMmD;CAwM1D;iBAlSgB,WAAW"}
|
package/dist/src/marks/text.js
CHANGED
|
@@ -243,7 +243,10 @@ export default class TextMark extends Mark {
|
|
|
243
243
|
fontMetrics: this.font.metrics,
|
|
244
244
|
numCharacters: Math.max(
|
|
245
245
|
charCount,
|
|
246
|
-
|
|
246
|
+
// There's some mysterious bug with growing the buffer –
|
|
247
|
+
// old buffer is rendered instead of the new one.
|
|
248
|
+
// TODO: Figure it out
|
|
249
|
+
this.properties.minBufferSize || 1024
|
|
247
250
|
),
|
|
248
251
|
});
|
|
249
252
|
|
package/dist/src/scale/scale.js
CHANGED
|
@@ -274,6 +274,8 @@ function rawDomain(scale, raw, logger) {
|
|
|
274
274
|
}
|
|
275
275
|
|
|
276
276
|
function padDomain(type, domain, range, pad, exponent, constant) {
|
|
277
|
+
range ??= [0, 1]; // default to unit range. TODO: Fix this when we have pixel-based ranges.
|
|
278
|
+
|
|
277
279
|
var span = Math.abs(peek(range) - range[0]),
|
|
278
280
|
frac = span / (span - 2 * pad),
|
|
279
281
|
d =
|
|
@@ -60,6 +60,25 @@ export interface BindBase {
|
|
|
60
60
|
description?: string;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
export interface BindInput extends BindBase {
|
|
64
|
+
/**
|
|
65
|
+
* The type of input element to use.
|
|
66
|
+
* The valid values are `"checkbox"`, `"radio"`, `"range"`, `"select"`, `"text"`, `"number"`, and `"color"`.
|
|
67
|
+
*/
|
|
68
|
+
input?: "text" | "number" | "color";
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Text that appears in the form control when it has no value set.
|
|
72
|
+
*/
|
|
73
|
+
placeholder?: string;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* A hint for form autofill.
|
|
77
|
+
* See the [HTML autocomplete attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) for additional information.
|
|
78
|
+
*/
|
|
79
|
+
autocomplete?: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
63
82
|
export interface BindCheckbox extends BindBase {
|
|
64
83
|
input: "checkbox";
|
|
65
84
|
}
|
|
@@ -124,4 +143,4 @@ export interface BindDirect {
|
|
|
124
143
|
debounce?: number;
|
|
125
144
|
}
|
|
126
145
|
|
|
127
|
-
export type Binding = BindCheckbox | BindRadioSelect | BindRange;
|
|
146
|
+
export type Binding = BindCheckbox | BindRadioSelect | BindRange | BindInput;
|
|
@@ -33,6 +33,13 @@ export interface EmbedOptions {
|
|
|
33
33
|
* the input binding elements are placed in the same container as the GenomeSpy instance.
|
|
34
34
|
*/
|
|
35
35
|
inputBindingContainer?: HTMLElement | "none" | "default";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A suggestion for the browser on the appropriate GPU setup for the WebGL environment.
|
|
39
|
+
* Defaults to "default" in the @genome-spy/core package and "high-performance" in the
|
|
40
|
+
* @genome-spy/app package.
|
|
41
|
+
*/
|
|
42
|
+
powerPreference?: "default" | "high-performance" | "low-power";
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
/**
|
|
@@ -24,6 +24,12 @@ export interface RenderingOptions {
|
|
|
24
24
|
*/
|
|
25
25
|
facetId?: any;
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* If rendering facets, this is the first facet. Allows for
|
|
29
|
+
* cleanup, etc.
|
|
30
|
+
*/
|
|
31
|
+
firstFacet?: boolean;
|
|
32
|
+
|
|
27
33
|
sampleFacetRenderingOptions?: SampleFacetRenderingOptions;
|
|
28
34
|
|
|
29
35
|
/**
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns a lerp smoother that animates a value towards a target value. Lerp smoothing
|
|
3
|
+
* is conceptually similar to easing, but can be used when the current and target
|
|
4
|
+
* values are not known in advance.
|
|
5
|
+
*
|
|
6
|
+
* Read more at: https://www.gamedeveloper.com/programming/improved-lerp-smoothing-
|
|
7
|
+
*
|
|
8
|
+
* @param {import("../utils/animator.js").default} animator
|
|
9
|
+
* @param {(value: number) => void} callback Function to be called with the interpolated value
|
|
10
|
+
* @param {number} halfLife Time until half of the value is reached, in milliseconds
|
|
11
|
+
* @param {number} stopAt Stop animation when the value is within this distance from the target
|
|
12
|
+
* @param {number} [initialValue] Initial value
|
|
13
|
+
* @returns {(target: number) => void} Function that activates the transition with a new target value
|
|
14
|
+
*/
|
|
15
|
+
export function makeLerpSmoother(animator: import("../utils/animator.js").default, callback: (value: number) => void, halfLife: number, stopAt: number, initialValue?: number): (target: number) => void;
|
|
1
16
|
export default class Animator {
|
|
2
17
|
/**
|
|
3
18
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"animator.d.ts","sourceRoot":"","sources":["../../../src/utils/animator.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"animator.d.ts","sourceRoot":"","sources":["../../../src/utils/animator.js"],"names":[],"mappings":"AAoFA;;;;;;;;;;;;;GAaG;AACH,2CAPW,OAAO,sBAAsB,EAAE,OAAO,oBAC9B,MAAM,KAAK,IAAI,YACvB,MAAM,UACN,MAAM,iBACN,MAAM,YACK,MAAM,KAAK,IAAI,CAoDpC;AAlJD;IACI;;;OAGG;IACH,mCAFoB,MAAM,KAAE,IAAI,EAS/B;IANG,wBAHgB,MAAM,KAAE,IAAI,CAGS;IACrC,0BAA6B;IAC7B,eAAkB;IAElB,wCAAwC;IACxC,aADW,QAAU,MAAM,KAAE,IAAI,CAAC,EAAE,CACf;IAGzB;;;;;;;;;OASG;IACH,mCAFoB,MAAM,KAAE,IAAI,QAM/B;IAED;;OAEG;IACH,kCAFoB,MAAM,KAAE,IAAI,QAO/B;IAED;;;;OAIG;IACH,sBAoBC;IAED;;;;;OAKG;IACH,oBAFW,OAAO,iBAAiB,EAAE,iBAAiB,gBAQrD;CACJ"}
|
|
@@ -81,3 +81,69 @@ export default class Animator {
|
|
|
81
81
|
});
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Returns a lerp smoother that animates a value towards a target value. Lerp smoothing
|
|
87
|
+
* is conceptually similar to easing, but can be used when the current and target
|
|
88
|
+
* values are not known in advance.
|
|
89
|
+
*
|
|
90
|
+
* Read more at: https://www.gamedeveloper.com/programming/improved-lerp-smoothing-
|
|
91
|
+
*
|
|
92
|
+
* @param {import("../utils/animator.js").default} animator
|
|
93
|
+
* @param {(value: number) => void} callback Function to be called with the interpolated value
|
|
94
|
+
* @param {number} halfLife Time until half of the value is reached, in milliseconds
|
|
95
|
+
* @param {number} stopAt Stop animation when the value is within this distance from the target
|
|
96
|
+
* @param {number} [initialValue] Initial value
|
|
97
|
+
* @returns {(target: number) => void} Function that activates the transition with a new target value
|
|
98
|
+
*/
|
|
99
|
+
export function makeLerpSmoother(
|
|
100
|
+
animator,
|
|
101
|
+
callback,
|
|
102
|
+
halfLife,
|
|
103
|
+
stopAt,
|
|
104
|
+
initialValue = 0
|
|
105
|
+
) {
|
|
106
|
+
let lastTimeStamp = 0;
|
|
107
|
+
let settled = true;
|
|
108
|
+
|
|
109
|
+
let current = initialValue;
|
|
110
|
+
let target = current;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @param {number} [timestamp]
|
|
114
|
+
*/
|
|
115
|
+
function smoothUpdate(timestamp) {
|
|
116
|
+
timestamp ??= +document.timeline.currentTime;
|
|
117
|
+
|
|
118
|
+
// If settled, the animation loop may have been stopped, so we need to
|
|
119
|
+
// wait until the next frame to get a proper time delta.
|
|
120
|
+
const tD = settled ? 0 : timestamp - lastTimeStamp;
|
|
121
|
+
lastTimeStamp = timestamp;
|
|
122
|
+
|
|
123
|
+
settled = false;
|
|
124
|
+
|
|
125
|
+
// Lerp smoothing: https://twitter.com/FreyaHolmer/status/1757836988495847568
|
|
126
|
+
current = target + (current - target) * Math.pow(2, -tD / halfLife);
|
|
127
|
+
|
|
128
|
+
callback(current);
|
|
129
|
+
|
|
130
|
+
if (Math.abs(target - current) < stopAt) {
|
|
131
|
+
current = target;
|
|
132
|
+
callback(current);
|
|
133
|
+
settled = true;
|
|
134
|
+
animator.requestRender();
|
|
135
|
+
} else {
|
|
136
|
+
animator.requestTransition((t) => smoothUpdate(t));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* @param {number} value
|
|
142
|
+
*/
|
|
143
|
+
return function setTarget(value) {
|
|
144
|
+
target = value;
|
|
145
|
+
if (settled) {
|
|
146
|
+
smoothUpdate();
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
}
|
|
@@ -14,18 +14,12 @@ export default class Inertia {
|
|
|
14
14
|
constructor(animator: import("./animator.js").default, disabled?: boolean);
|
|
15
15
|
animator: import("./animator.js").default;
|
|
16
16
|
disabled: boolean;
|
|
17
|
-
|
|
18
|
-
acceleration: number;
|
|
19
|
-
/** Use acceleration if the momentum step is greater than X */
|
|
20
|
-
accelerationThreshold: number;
|
|
21
|
-
lowerLimit: number;
|
|
22
|
-
loop: boolean;
|
|
23
|
-
momentum: number;
|
|
24
|
-
timestamp: number;
|
|
17
|
+
maxDistance: number;
|
|
25
18
|
/** @type {function(number):void} */
|
|
26
19
|
callback: (arg0: number) => void;
|
|
27
|
-
|
|
28
|
-
|
|
20
|
+
targetValue: number;
|
|
21
|
+
lastValue: number;
|
|
22
|
+
smoother: (target: number) => void;
|
|
29
23
|
cancel(): void;
|
|
30
24
|
/**
|
|
31
25
|
*
|
|
@@ -33,10 +27,5 @@ export default class Inertia {
|
|
|
33
27
|
* @param {function(number):void} callback
|
|
34
28
|
*/
|
|
35
29
|
setMomentum(value: number, callback: (arg0: number) => void): void;
|
|
36
|
-
/**
|
|
37
|
-
*
|
|
38
|
-
* @param {number} [timestamp]
|
|
39
|
-
*/
|
|
40
|
-
animate(timestamp?: number): void;
|
|
41
30
|
}
|
|
42
31
|
//# sourceMappingURL=inertia.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inertia.d.ts","sourceRoot":"","sources":["../../../src/utils/inertia.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"inertia.d.ts","sourceRoot":"","sources":["../../../src/utils/inertia.js"],"names":[],"mappings":"AAmEA;;;GAGG;AACH,8EAiBC;AApFD;;GAEG;AACH;IACI;;;OAGG;IACH,sBAHW,OAAO,eAAe,EAAE,OAAO,aAC/B,OAAO,EAyBjB;IAtBG,0CAAwB;IACxB,kBAA0B;IAG1B,oBAAsB;IAEtB,oCAAoC;IACpC,iBADoB,MAAM,KAAE,IAAI,CACZ;IAEpB,oBAAoB;IACpB,kBAAkB;IAElB,mCASC;IAGL,eAIC;IAED;;;;OAIG;IACH,mBAHW,MAAM,mBACG,MAAM,KAAE,IAAI,QAkB/B;CACJ"}
|
|
@@ -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
|
|