@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
package/dist/schema.json
CHANGED
|
@@ -507,6 +507,41 @@
|
|
|
507
507
|
],
|
|
508
508
|
"type": "object"
|
|
509
509
|
},
|
|
510
|
+
"BindInput": {
|
|
511
|
+
"additionalProperties": false,
|
|
512
|
+
"properties": {
|
|
513
|
+
"autocomplete": {
|
|
514
|
+
"description": "A hint for form autofill. See the [HTML autocomplete attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete) for additional information.",
|
|
515
|
+
"type": "string"
|
|
516
|
+
},
|
|
517
|
+
"debounce": {
|
|
518
|
+
"description": "If defined, delays event handling until the specified milliseconds have elapsed since the last event was fired.",
|
|
519
|
+
"type": "number"
|
|
520
|
+
},
|
|
521
|
+
"description": {
|
|
522
|
+
"description": "An optional description or help text that is shown below the input element.",
|
|
523
|
+
"type": "string"
|
|
524
|
+
},
|
|
525
|
+
"input": {
|
|
526
|
+
"description": "The type of input element to use. The valid values are `\"checkbox\"`, `\"radio\"`, `\"range\"`, `\"select\"`, `\"text\"`, `\"number\"`, and `\"color\"`.",
|
|
527
|
+
"enum": [
|
|
528
|
+
"text",
|
|
529
|
+
"number",
|
|
530
|
+
"color"
|
|
531
|
+
],
|
|
532
|
+
"type": "string"
|
|
533
|
+
},
|
|
534
|
+
"name": {
|
|
535
|
+
"description": "By default, the parameter name is used to label input elements. This `name` property can be used instead to specify a custom label for the bound parameter.",
|
|
536
|
+
"type": "string"
|
|
537
|
+
},
|
|
538
|
+
"placeholder": {
|
|
539
|
+
"description": "Text that appears in the form control when it has no value set.",
|
|
540
|
+
"type": "string"
|
|
541
|
+
}
|
|
542
|
+
},
|
|
543
|
+
"type": "object"
|
|
544
|
+
},
|
|
510
545
|
"BindRadioSelect": {
|
|
511
546
|
"additionalProperties": false,
|
|
512
547
|
"properties": {
|
|
@@ -595,6 +630,9 @@
|
|
|
595
630
|
},
|
|
596
631
|
{
|
|
597
632
|
"$ref": "#/definitions/BindRange"
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
"$ref": "#/definitions/BindInput"
|
|
598
636
|
}
|
|
599
637
|
]
|
|
600
638
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"genomeSpy.d.ts","sourceRoot":"","sources":["../../src/genomeSpy.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"genomeSpy.d.ts","sourceRoot":"","sources":["../../src/genomeSpy.js"],"names":[],"mappings":"AA+CA;IACI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EA2FpD;IAxFG,uBAA0B;IAC1B,oDAAsB;IAItB,6BAA6B;IAC7B,uBADW,CAAC,MAAM,IAAI,CAAC,EAAE,CACM;IAE/B,sCAAsC;IACtC,wCAAgB;IAEhB,iCAA4C;IAC5C,yBAAoC;IAEpC,4CAA4C;IAC5C,oBADW,QAAU,MAAM,KAAE,MAAM,EAAE,CAAC,EAAE,CACZ;IAE5B,mBAAoD;IAEpD,0BAA0B;IAC1B,aADW,WAAW,CACM;IAE5B;;;;;OAKG;IACH,qEAF0B,OAAO,CAE8B;IAE/D,2CAA2C;IAC3C,mBADW,4BAA4B,CACL;IAClC,2CAA2C;IAC3C,iBADW,4BAA4B,CACP;IAEhC,oDAAoD;IACpD,6BAAgC;IAEhC;;;OAGG;IACH,eAFU;QAAE,IAAI,EAAE,OAAO,iBAAiB,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,OAAO,oBAAoB,EAAE,KAAK,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAEpF;IAE9B,uBAA+C;IAE/C;;;OAGG;IACH,oBAFU,IAAI,MAAM,EAAE,QAAU,aAAa,KAAE,IAAI,CAAC,EAAE,CAAC,CAEpB;IAEnC;;;;;;OAMG;IACH,yCAFkC,GAAG,KAAK,IAAI,GAEd;IAEhC;;;OAGG;IACH,kDAFkC,GAAG,KAAK,IAAI,GAEL;IAEzC,oFAAoF;IACpF,iBADW,OAAO,MAAM,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC,CAK9E;IAED,mBAAmB;IACnB,2CAAyB;IAEzB;;;;OAIG;IACH;gBAF8B,OAAO,wBAAwB,EAAE,iBAAiB;iBAAW,MAAM;OAEnE;IAE9B;;OAEG;IACH,wBAFU,WAAW,CAEkB;IA2C3C;;;OAGG;IACH,2CAFkB,MAAM,KAAK,GAAG,EAAE,QAIjC;IAED;;OAEG;IACH,+BAFW,MAAM,YAShB;IAED;;;;OAIG;IACH,sBAHW,MAAM,QACN,GAAG,EAAE,QAaf;IAED;;;;;OAKG;IACH,gBAHW,kBAAkB,YAClB,GAAG,QAQb;IAED;;;OAGG;IACH,iCAqDC;IA0DG,uBAQC;IAGD,mCAGE;IAOF,sCAEE;IAGF,iBAAyC;IAW7C;;OAEG;IACH,gBAuBC;IAED,sCA8MC;IAED;;;OAGG;IACH,UAFa,QAAQ,OAAO,CAAC,CA6B5B;IAED,4BAqJC;IA9He,iCAAoC;IAgIpD;;;OAGG;IACH,kBAHW,MAAM,KACN,MAAM,QAsEhB;IAED;;;;;;;OAOG;IACH,oDAHuB,QAAQ,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAYlF;IAED,sBA6CC;IAED,kBAIC;IAED,iCAOC;IAED,iCASC;IAED,qFAWC;;CACJ;;;;iCAx7BY,eAAe,GAAG,YAAY,GAAG,QAAQ,GAAG,gBAAgB;4BAlC7C,uBAAuB;4BA2BP,uBAAuB;qBAZ9C,qBAAqB;wBAIlB,yBAAyB;yCARR,yDAAyD;oBAYvD,oBAAoB;wBAdvC,qBAAqB;oBAXzB,uBAAuB;qBAStB,oBAAoB"}
|
package/dist/src/genomeSpy.js
CHANGED
|
@@ -36,6 +36,7 @@ import { invalidatePrefix } from "./utils/propertyCacher.js";
|
|
|
36
36
|
import { VIEW_ROOT_NAME, ViewFactory } from "./view/viewFactory.js";
|
|
37
37
|
import { reconfigureScales } from "./view/scaleResolution.js";
|
|
38
38
|
import createBindingInputs from "./utils/inputBinding.js";
|
|
39
|
+
import { isStillZooming } from "./view/zoom.js";
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* Events that are broadcasted to all views.
|
|
@@ -362,7 +363,8 @@ export default class GenomeSpy {
|
|
|
362
363
|
this.viewRoot
|
|
363
364
|
? calculateCanvasSize(calculateViewRootSize(this.viewRoot))
|
|
364
365
|
: { width: undefined, height: undefined },
|
|
365
|
-
this.spec.background
|
|
366
|
+
this.spec.background,
|
|
367
|
+
{ powerPreference: this.options.powerPreference ?? "default" }
|
|
366
368
|
);
|
|
367
369
|
|
|
368
370
|
// The initial loading message that is shown until the first frame is rendered
|
|
@@ -668,25 +670,33 @@ export default class GenomeSpy {
|
|
|
668
670
|
// that would also contain state-related stuff that currently pollute the
|
|
669
671
|
// GenomeSpy class.
|
|
670
672
|
|
|
673
|
+
let lastWheelEvent = performance.now();
|
|
674
|
+
|
|
671
675
|
/** @param {Event} event */
|
|
672
676
|
const listener = (event) => {
|
|
677
|
+
const now = performance.now();
|
|
678
|
+
const wheeling = now - lastWheelEvent < 200;
|
|
679
|
+
|
|
673
680
|
if (event instanceof MouseEvent) {
|
|
674
|
-
|
|
681
|
+
const rect = canvas.getBoundingClientRect();
|
|
682
|
+
const point = new Point(
|
|
683
|
+
event.clientX - rect.left - canvas.clientLeft,
|
|
684
|
+
event.clientY - rect.top - canvas.clientTop
|
|
685
|
+
);
|
|
686
|
+
|
|
687
|
+
if (event.type == "mousemove" && !wheeling) {
|
|
675
688
|
this.tooltip.handleMouseMove(event);
|
|
676
689
|
this._tooltipUpdateRequested = false;
|
|
677
690
|
|
|
678
|
-
|
|
679
|
-
|
|
691
|
+
// Disable picking during dragging. Also postpone picking until
|
|
692
|
+
// the user has stopped zooming as reading pixels from the
|
|
693
|
+
// picking buffer is slow and ruins smooth animations.
|
|
694
|
+
if (event.buttons == 0 && !isStillZooming()) {
|
|
680
695
|
this.renderPickingFramebuffer();
|
|
696
|
+
this._handlePicking(point.x, point.y);
|
|
681
697
|
}
|
|
682
698
|
}
|
|
683
699
|
|
|
684
|
-
const rect = canvas.getBoundingClientRect();
|
|
685
|
-
const point = new Point(
|
|
686
|
-
event.clientX - rect.left - canvas.clientLeft,
|
|
687
|
-
event.clientY - rect.top - canvas.clientTop
|
|
688
|
-
);
|
|
689
|
-
|
|
690
700
|
/**
|
|
691
701
|
* @param {MouseEvent} event
|
|
692
702
|
*/
|
|
@@ -704,14 +714,14 @@ export default class GenomeSpy {
|
|
|
704
714
|
this._wheelInertia.cancel();
|
|
705
715
|
}
|
|
706
716
|
|
|
707
|
-
if (
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
event.type == "mousedown" ||
|
|
711
|
-
event.type == "mouseup"
|
|
717
|
+
if (
|
|
718
|
+
(event.type == "mousedown" || event.type == "mouseup") &&
|
|
719
|
+
!isStillZooming()
|
|
712
720
|
) {
|
|
721
|
+
// Actually, only needed when clicking on a mark
|
|
713
722
|
this.renderPickingFramebuffer();
|
|
714
723
|
} else if (event.type == "wheel") {
|
|
724
|
+
lastWheelEvent = now;
|
|
715
725
|
this._tooltipUpdateRequested = false;
|
|
716
726
|
|
|
717
727
|
const wheelEvent = /** @type {WheelEvent} */ (event);
|
|
@@ -830,7 +840,12 @@ export default class GenomeSpy {
|
|
|
830
840
|
|
|
831
841
|
this.viewRoot.visit((view) => {
|
|
832
842
|
if (view instanceof UnitView) {
|
|
833
|
-
if (
|
|
843
|
+
if (
|
|
844
|
+
view.mark.isPickingParticipant() &&
|
|
845
|
+
[...view.facetCoords.values()].some((coords) =>
|
|
846
|
+
coords.containsPoint(x, y)
|
|
847
|
+
)
|
|
848
|
+
) {
|
|
834
849
|
const accessor = view.mark.encoders.uniqueId.accessor;
|
|
835
850
|
view.getCollector().visitData((d) => {
|
|
836
851
|
if (accessor(d) == uniqueId) {
|
|
@@ -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,20 @@
|
|
|
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) & { stop: () => 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) & {
|
|
16
|
+
stop: () => void;
|
|
17
|
+
};
|
|
1
18
|
export default class Animator {
|
|
2
19
|
/**
|
|
3
20
|
*
|
|
@@ -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,aACM,MAAM,KAAK,IAAI;UAAY,MAAM,IAAI;EA0D3D;AAxJD;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,75 @@ 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) & { stop: () => 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
|
+
if (settled) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const tD = timestamp - lastTimeStamp;
|
|
121
|
+
lastTimeStamp = timestamp;
|
|
122
|
+
|
|
123
|
+
// Lerp smoothing: https://twitter.com/FreyaHolmer/status/1757836988495847568
|
|
124
|
+
current = target + (current - target) * Math.pow(2, -tD / halfLife);
|
|
125
|
+
|
|
126
|
+
callback(current);
|
|
127
|
+
|
|
128
|
+
if (Math.abs(target - current) < stopAt) {
|
|
129
|
+
current = target;
|
|
130
|
+
callback(current);
|
|
131
|
+
settled = true;
|
|
132
|
+
animator.requestRender();
|
|
133
|
+
} else {
|
|
134
|
+
animator.requestTransition((t) => smoothUpdate(t));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* @param {number} value
|
|
140
|
+
*/
|
|
141
|
+
function setTarget(value) {
|
|
142
|
+
target = value;
|
|
143
|
+
if (settled) {
|
|
144
|
+
settled = false;
|
|
145
|
+
lastTimeStamp = +document.timeline.currentTime;
|
|
146
|
+
smoothUpdate(lastTimeStamp);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
setTarget.stop = () => {
|
|
151
|
+
settled = true;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
return setTarget;
|
|
155
|
+
}
|
|
@@ -14,18 +14,14 @@ 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) & {
|
|
23
|
+
stop: () => void;
|
|
24
|
+
};
|
|
29
25
|
cancel(): void;
|
|
30
26
|
/**
|
|
31
27
|
*
|
|
@@ -33,10 +29,5 @@ export default class Inertia {
|
|
|
33
29
|
* @param {function(number):void} callback
|
|
34
30
|
*/
|
|
35
31
|
setMomentum(value: number, callback: (arg0: number) => void): void;
|
|
36
|
-
/**
|
|
37
|
-
*
|
|
38
|
-
* @param {number} [timestamp]
|
|
39
|
-
*/
|
|
40
|
-
animate(timestamp?: number): void;
|
|
41
32
|
}
|
|
42
33
|
//# 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;;MASC;IAGL,eAIC;IAED;;;;OAIG;IACH,mBAHW,MAAM,mBACG,MAAM,KAAE,IAAI,QAkB/B;CACJ"}
|