@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.
Files changed (51) hide show
  1. package/dist/bundle/index.es.js +5310 -5113
  2. package/dist/bundle/index.js +105 -94
  3. package/dist/schema.json +38 -0
  4. package/dist/src/genomeSpy.d.ts.map +1 -1
  5. package/dist/src/genomeSpy.js +31 -16
  6. package/dist/src/gl/webGLHelper.d.ts +2 -1
  7. package/dist/src/gl/webGLHelper.d.ts.map +1 -1
  8. package/dist/src/gl/webGLHelper.js +8 -1
  9. package/dist/src/marks/mark.d.ts +24 -12
  10. package/dist/src/marks/mark.d.ts.map +1 -1
  11. package/dist/src/marks/mark.js +27 -13
  12. package/dist/src/marks/point.d.ts +0 -1
  13. package/dist/src/marks/point.d.ts.map +1 -1
  14. package/dist/src/marks/point.js +6 -2
  15. package/dist/src/marks/text.d.ts.map +1 -1
  16. package/dist/src/marks/text.js +4 -1
  17. package/dist/src/scale/scale.js +2 -0
  18. package/dist/src/spec/parameter.d.ts +20 -1
  19. package/dist/src/types/embedApi.d.ts +7 -0
  20. package/dist/src/types/rendering.d.ts +6 -0
  21. package/dist/src/utils/animator.d.ts +17 -0
  22. package/dist/src/utils/animator.d.ts.map +1 -1
  23. package/dist/src/utils/animator.js +72 -0
  24. package/dist/src/utils/inertia.d.ts +6 -15
  25. package/dist/src/utils/inertia.d.ts.map +1 -1
  26. package/dist/src/utils/inertia.js +28 -63
  27. package/dist/src/utils/inputBinding.d.ts.map +1 -1
  28. package/dist/src/utils/inputBinding.js +26 -2
  29. package/dist/src/utils/ringBuffer.d.ts +19 -0
  30. package/dist/src/utils/ringBuffer.d.ts.map +1 -0
  31. package/dist/src/utils/ringBuffer.js +43 -0
  32. package/dist/src/utils/ringBuffer.test.js +39 -0
  33. package/dist/src/view/gridView.d.ts +6 -6
  34. package/dist/src/view/gridView.d.ts.map +1 -1
  35. package/dist/src/view/gridView.js +48 -29
  36. package/dist/src/view/layout/point.d.ts +17 -1
  37. package/dist/src/view/layout/point.d.ts.map +1 -1
  38. package/dist/src/view/layout/point.js +36 -1
  39. package/dist/src/view/unitView.d.ts +3 -14
  40. package/dist/src/view/unitView.d.ts.map +1 -1
  41. package/dist/src/view/unitView.js +26 -8
  42. package/dist/src/view/view.d.ts +14 -5
  43. package/dist/src/view/view.d.ts.map +1 -1
  44. package/dist/src/view/view.js +26 -7
  45. package/dist/src/view/zoom.d.ts +4 -10
  46. package/dist/src/view/zoom.d.ts.map +1 -1
  47. package/dist/src/view/zoom.js +126 -9
  48. package/package.json +2 -2
  49. package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.d.ts +0 -60
  50. package/dist/src/view/renderingContext/layoutRecorderViewRenderingContext.d.ts.map +0 -1
  51. 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":"AA8CA;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,uBAOC;IAGD,mCAGE;IAOF,sCAEE;IAGF,iBAAyC;IAW7C;;OAEG;IACH,gBAuBC;IAED,sCA8MC;IAED;;;OAGG;IACH,UAFa,QAAQ,OAAO,CAAC,CA6B5B;IAED,4BA6IC;IAjIe,iCAAoC;IAmIpD;;;OAGG;IACH,kBAHW,MAAM,KACN,MAAM,QAiEhB;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;;;;iCA16BY,eAAe,GAAG,YAAY,GAAG,QAAQ,GAAG,gBAAgB;4BAjC7C,uBAAuB;4BA2BP,uBAAuB;qBAZ9C,qBAAqB;wBAIlB,yBAAyB;yCARR,yDAAyD;oBAYvD,oBAAoB;wBAdvC,qBAAqB;oBAXzB,uBAAuB;qBAStB,oBAAoB"}
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"}
@@ -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
- if (event.type == "mousemove") {
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
- if (event.buttons == 0) {
679
- // Disable during dragging
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 (event.type == "mousemove") {
708
- this._handlePicking(point.x, point.y);
709
- } else if (
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 (view.mark.isPickingParticipant()) {
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":"AA4ZA;;;;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;AAjcD;IACI;;;;;;;OAOG;IACH,uBANW,WAAW,eACX,MAAM;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,eAGrC,MAAM,EAmFhB;IAhFG,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;IAuClC,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"}
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(container, sizeSource, clearColor) {
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
 
@@ -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
- /** @type {import("twgl.js").BufferInfo & { allocatedVertices?: number }} WebGL buffers */
26
- bufferInfo: import("twgl.js").BufferInfo & {
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
- /** @type {import("twgl.js").ProgramInfo} WebGL buffers */
30
- programInfo: import("twgl.js").ProgramInfo;
31
- /** @type {import("twgl.js").VertexArrayInfo} WebGL buffers */
32
- vertexArrayInfo: import("twgl.js").VertexArrayInfo;
33
- /** @type {import("twgl.js").UniformBlockInfo} WebGL buffers */
34
- domainUniformInfo: import("twgl.js").UniformBlockInfo;
35
- /** @type {import("twgl.js").UniformBlockInfo} WebGL buffers */
36
- viewUniformInfo: import("twgl.js").UniformBlockInfo;
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,EAkF/C;IA/EG,gDAAwB;IAExB,oEAAoE;IACpE,UADW,OAAO,MAAM,EAAE,OAAO,qBAAqB,EAAE,OAAO,CAAC,CACvC;IAIzB,0FAA0F;IAC1F,YADW,OAAO,SAAS,EAAE,UAAU,GAAG;QAAE,iBAAiB,CAAC,EAAE,MAAM,CAAA;KAAE,CAC7C;IAE3B,0DAA0D;IAC1D,aADW,OAAO,SAAS,EAAE,WAAW,CACZ;IAE5B,8DAA8D;IAC9D,iBADW,OAAO,SAAS,EAAE,eAAe,CACZ;IAEhC,+DAA+D;IAC/D,mBADW,OAAO,SAAS,EAAE,gBAAgB,CACX;IAElC,+DAA+D;IAC/D,iBADW,OAAO,SAAS,EAAE,gBAAgB,CACb;IAEhC;;;OAGG;IACH,iBAFU,OAAO,SAAS,EAAE,gBAAgB,CAEZ;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,2BAiBC;IAED;;;OAGG;IACH,6BAFW,GAAG,QAoCb;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;+BAznCY,OAAO,uBAAuB,EAAE,gBAAgB;;;;;;wBAEnD,OAAO;;mCAEJ,gBAAgB,GAAG,qBAAqB;oCAG1C,MAAM,SACN,MAAM;AAmnCjB;;;GAGG;AACH;IACI,cAEC;IAkBD;;;OAGG;IACH,2BAFW,IAAI,CAAC,EAAE,OAAO,yBAAyB,EAAE,UAAU,CAAC,QAiB9D;CACJ;0BAjrCyB,WAAW"}
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"}
@@ -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
- /** @type {import("twgl.js").BufferInfo & { allocatedVertices?: number }} WebGL buffers */
88
+ /**
89
+ * @type {import("twgl.js").BufferInfo & { allocatedVertices?: number }}
90
+ * @protected
91
+ */
89
92
  this.bufferInfo = undefined;
90
93
 
91
- /** @type {import("twgl.js").ProgramInfo} WebGL buffers */
94
+ /**
95
+ * @type {import("twgl.js").ProgramInfo}
96
+ * @protected
97
+ */
92
98
  this.programInfo = undefined;
93
99
 
94
- /** @type {import("twgl.js").VertexArrayInfo} WebGL buffers */
100
+ /**
101
+ * @type {import("twgl.js").VertexArrayInfo}
102
+ * @protected
103
+ */
95
104
  this.vertexArrayInfo = undefined;
96
105
 
97
- /** @type {import("twgl.js").UniformBlockInfo} WebGL buffers */
98
- this.domainUniformInfo = undefined;
99
-
100
- /** @type {import("twgl.js").UniformBlockInfo} WebGL buffers */
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,6 +1,5 @@
1
1
  export default class PointMark extends Mark {
2
2
  sampledSemanticScores: Float32Array;
3
- _getGeometricScaleFactor(): number;
4
3
  getSemanticThreshold(): number;
5
4
  #private;
6
5
  }
@@ -1 +1 @@
1
- {"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/marks/point.js"],"names":[],"mappings":"AAmBA;IA0HY,oCAMC;IA+CT,mCAQC;IAED,+BAkBC;;CAgDJ;iBAnQgB,WAAW"}
1
+ {"version":3,"file":"point.d.ts","sourceRoot":"","sources":["../../../src/marks/point.js"],"names":[],"mappings":"AAmBA;IA0HY,oCAMC;IA6DT,+BAkBC;;CAgDJ;iBAvQgB,WAAW"}
@@ -192,7 +192,11 @@ export default class PointMark extends Mark {
192
192
  this.updateBufferInfo(vertexData);
193
193
  }
194
194
 
195
- _getGeometricScaleFactor() {
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._getGeometricScaleFactor(),
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;CAqM1D;iBA/RgB,WAAW"}
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../../src/marks/text.js"],"names":[],"mappings":"AAgCA;;;;;;;GAOG;AACH;IAyDQ,oDAMmD;CAwM1D;iBAlSgB,WAAW"}
@@ -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
- this.properties.minBufferSize || 0
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
 
@@ -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":"AAEA;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"}
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
- damping: number;
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
- _transitionCallback: any;
28
- clear(): void;
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":"AAsGA;;;GAGG;AACH,8EAiBC;AAzHD;;GAEG;AACH;IACI;;;OAGG;IACH,sBAHW,OAAO,eAAe,EAAE,OAAO,aAC/B,OAAO,EAmBjB;IAhBG,0CAAwB;IACxB,kBAA0B;IAC1B,gBAAoB;IACpB,qBAAuB;IACvB,8DAA8D;IAC9D,8BAAgC;IAChC,mBAAqB;IACrB,cAAiB;IAEjB,UAUW,MAAM,CAVA;IACjB,kBAAkB;IAClB,oCAAoC;IACpC,iBADoB,MAAM,KAAE,IAAI,CACZ;IAEpB,yBAAkD;IAItD,cAMC;IAED,eAKC;IAED;;;;OAIG;IACH,mBAHW,MAAM,mBACG,MAAM,KAAE,IAAI,QAyB/B;IAED;;;OAGG;IACH,oBAFW,MAAM,QAuBhB;CACJ"}
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"}