@genome-spy/core 0.63.0 → 0.65.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-CCJIjehY.js → AbortablePromiseCache-CcuMrnn7.js} +22 -91
- package/dist/bundle/browser-txUcLy2H.js +123 -0
- package/dist/bundle/index-BQpbYrv4.js +1712 -0
- package/dist/bundle/index-BhtHKLUo.js +73 -0
- package/dist/bundle/index-C0llXMqm.js +280 -0
- package/dist/bundle/index-CCe8rnZz.js +716 -0
- package/dist/bundle/index-CD7FLu9x.js +269 -0
- package/dist/bundle/{index-C08YCM2T.js → index-D-w7Mmt9.js} +246 -126
- package/dist/bundle/index-D74H8TTz.js +508 -0
- package/dist/bundle/index-DhcU-Gk-.js +1487 -0
- package/dist/bundle/index.es.js +5394 -4989
- package/dist/bundle/index.js +420 -362
- package/dist/bundle/inflate-DRgHi_KK.js +1050 -0
- package/dist/schema.json +93 -13
- package/dist/src/data/collector.d.ts +7 -2
- package/dist/src/data/collector.d.ts.map +1 -1
- package/dist/src/data/collector.js +13 -2
- package/dist/src/data/dataFlow.d.ts +20 -42
- package/dist/src/data/dataFlow.d.ts.map +1 -1
- package/dist/src/data/dataFlow.js +57 -80
- package/dist/src/data/dataFlow.test.js +35 -2
- package/dist/src/data/flowHandle.d.ts +15 -0
- package/dist/src/data/flowHandle.d.ts.map +1 -0
- package/dist/src/data/flowHandle.js +13 -0
- package/dist/src/data/flowInit.d.ts +85 -0
- package/dist/src/data/flowInit.d.ts.map +1 -0
- package/dist/src/data/flowInit.js +238 -0
- package/dist/src/data/flowInit.test.d.ts +2 -0
- package/dist/src/data/flowInit.test.d.ts.map +1 -0
- package/dist/src/data/flowInit.test.js +413 -0
- package/dist/src/data/flowOptimizer.d.ts +6 -4
- package/dist/src/data/flowOptimizer.d.ts.map +1 -1
- package/dist/src/data/flowOptimizer.js +29 -14
- package/dist/src/data/flowOptimizer.test.js +20 -15
- package/dist/src/data/sources/lazy/bamSource.js +1 -1
- package/dist/src/data/sources/lazy/bigBedSource.js +1 -1
- package/dist/src/data/sources/lazy/bigWigSource.js +1 -1
- package/dist/src/data/sources/lazy/gff3Source.d.ts +2 -6
- package/dist/src/data/sources/lazy/gff3Source.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/gff3Source.js +4 -8
- package/dist/src/data/sources/lazy/indexedFastaSource.d.ts.map +1 -1
- package/dist/src/data/sources/lazy/indexedFastaSource.js +17 -17
- package/dist/src/data/sources/lazy/tabixSource.js +1 -1
- package/dist/src/genomeSpy.d.ts +1 -1
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +18 -61
- package/dist/src/gl/webGLHelper.d.ts.map +1 -1
- package/dist/src/gl/webGLHelper.js +8 -0
- package/dist/src/marks/link.fragment.glsl.js +1 -1
- package/dist/src/marks/link.vertex.glsl.js +1 -1
- package/dist/src/marks/mark.d.ts +1 -0
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +22 -1
- package/dist/src/marks/point.fragment.glsl.js +1 -1
- package/dist/src/marks/point.vertex.glsl.js +1 -1
- package/dist/src/marks/rect.fragment.glsl.js +1 -1
- package/dist/src/marks/rect.vertex.glsl.js +1 -1
- package/dist/src/marks/rule.fragment.glsl.js +1 -1
- package/dist/src/marks/rule.vertex.glsl.js +1 -1
- package/dist/src/marks/text.fragment.glsl.js +1 -1
- package/dist/src/marks/text.vertex.glsl.js +1 -1
- package/dist/src/selection/selection.d.ts +5 -0
- package/dist/src/selection/selection.d.ts.map +1 -1
- package/dist/src/selection/selection.js +43 -6
- package/dist/src/selection/selection.test.d.ts +2 -0
- package/dist/src/selection/selection.test.d.ts.map +1 -0
- package/dist/src/selection/selection.test.js +14 -0
- package/dist/src/spec/parameter.d.ts +28 -2
- package/dist/src/spec/sampleView.d.ts +3 -2
- package/dist/src/styles/{genome-spy.scss → genome-spy.css} +25 -21
- package/dist/src/styles/genome-spy.css.d.ts +1 -1
- package/dist/src/styles/genome-spy.css.d.ts.map +1 -1
- package/dist/src/styles/genome-spy.css.js +264 -195
- package/dist/src/styles/update.sh +14 -4
- package/dist/src/types/viewContext.d.ts +1 -1
- package/dist/src/utils/expression.d.ts +5 -0
- package/dist/src/utils/expression.d.ts.map +1 -1
- package/dist/src/utils/expression.js +37 -0
- package/dist/src/utils/interactionEvent.d.ts +18 -1
- package/dist/src/utils/interactionEvent.d.ts.map +1 -1
- package/dist/src/utils/interactionEvent.js +101 -1
- package/dist/src/utils/interactionEvent.test.d.ts +2 -0
- package/dist/src/utils/interactionEvent.test.d.ts.map +1 -0
- package/dist/src/utils/interactionEvent.test.js +35 -0
- package/dist/src/view/axisResolution.d.ts +5 -0
- package/dist/src/view/axisResolution.d.ts.map +1 -1
- package/dist/src/view/axisResolution.js +16 -1
- package/dist/src/view/facetView.d.ts +1 -1
- package/dist/src/view/facetView.d.ts.map +1 -1
- package/dist/src/view/facetView.js +1 -0
- package/dist/src/view/flowBuilder.d.ts +2 -2
- package/dist/src/view/flowBuilder.d.ts.map +1 -1
- package/dist/src/view/flowBuilder.js +21 -4
- package/dist/src/view/gridView/gridView.d.ts.map +1 -1
- package/dist/src/view/gridView/gridView.js +13 -0
- package/dist/src/view/gridView/selectionRect.d.ts +8 -4
- package/dist/src/view/gridView/selectionRect.d.ts.map +1 -1
- package/dist/src/view/gridView/selectionRect.js +28 -3
- package/dist/src/view/gridView/selectionRect.test.d.ts +2 -0
- package/dist/src/view/gridView/selectionRect.test.d.ts.map +1 -0
- package/dist/src/view/gridView/selectionRect.test.js +87 -0
- package/dist/src/view/paramMediator.d.ts +2 -1
- package/dist/src/view/paramMediator.d.ts.map +1 -1
- package/dist/src/view/paramMediator.js +13 -1
- package/dist/src/view/paramMediator.test.js +22 -0
- package/dist/src/view/scaleResolution.d.ts +5 -0
- package/dist/src/view/scaleResolution.d.ts.map +1 -1
- package/dist/src/view/scaleResolution.js +10 -0
- package/dist/src/view/testUtils.d.ts.map +1 -1
- package/dist/src/view/testUtils.js +16 -4
- package/dist/src/view/unitView.d.ts.map +1 -1
- package/dist/src/view/unitView.js +103 -10
- package/dist/src/view/view.d.ts +17 -1
- package/dist/src/view/view.d.ts.map +1 -1
- package/dist/src/view/view.js +57 -1
- package/dist/src/view/viewDispose.test.d.ts +2 -0
- package/dist/src/view/viewDispose.test.d.ts.map +1 -0
- package/dist/src/view/viewDispose.test.js +110 -0
- package/dist/src/view/viewUtils.d.ts +4 -4
- package/dist/src/view/viewUtils.d.ts.map +1 -1
- package/dist/src/view/viewUtils.js +19 -15
- package/dist/src/view/viewUtils.test.d.ts +2 -0
- package/dist/src/view/viewUtils.test.d.ts.map +1 -0
- package/dist/src/view/viewUtils.test.js +87 -0
- package/package.json +16 -16
- package/dist/bundle/__vite-browser-external-C--ziKoh.js +0 -8
- package/dist/bundle/_commonjsHelpers-DjF3Plf2.js +0 -26
- package/dist/bundle/index-5ajWdKly.js +0 -1319
- package/dist/bundle/index-B03-Om4z.js +0 -274
- package/dist/bundle/index-BftNdA0O.js +0 -27
- package/dist/bundle/index-Bg7C4Xat.js +0 -2750
- package/dist/bundle/index-C3QR8Lv6.js +0 -2131
- package/dist/bundle/index-DTcHjAHp.js +0 -505
- package/dist/bundle/index-DnIkxb0L.js +0 -1025
- package/dist/bundle/index-Ww3TAo6_.js +0 -71
- package/dist/bundle/index-g8iXgW0W.js +0 -651
- package/dist/bundle/long-B-FASCSo.js +0 -2387
- package/dist/bundle/remoteFile-BuaqFGWk.js +0 -94
|
@@ -28,16 +28,9 @@ export default class IndexedFastaSource extends SingleAxisWindowedSource {
|
|
|
28
28
|
|
|
29
29
|
this.initializedPromise = new Promise((resolve) => {
|
|
30
30
|
Promise.all([
|
|
31
|
-
import("buffer"),
|
|
32
31
|
import("@gmod/indexedfasta"),
|
|
33
|
-
import("generic-
|
|
34
|
-
]).then(([{
|
|
35
|
-
// Hack needed by @gmod/indexedfasta
|
|
36
|
-
// TODO: Submit a PR to @gmod/indexedfasta to make this unnecessary
|
|
37
|
-
if (typeof window !== "undefined") {
|
|
38
|
-
window.Buffer ??= Buffer;
|
|
39
|
-
}
|
|
40
|
-
|
|
32
|
+
import("generic-filehandle2"),
|
|
33
|
+
]).then(([{ IndexedFasta }, { RemoteFile }]) => {
|
|
41
34
|
const withBase = (/** @type {string} */ uri) =>
|
|
42
35
|
new RemoteFile(addBaseUrl(uri, this.view.getBaseUrl()));
|
|
43
36
|
|
|
@@ -68,15 +61,22 @@ export default class IndexedFastaSource extends SingleAxisWindowedSource {
|
|
|
68
61
|
.getSequence(d.chrom, d.startPos, d.endPos, {
|
|
69
62
|
signal,
|
|
70
63
|
})
|
|
71
|
-
.then((sequence) =>
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
.then((sequence) => {
|
|
65
|
+
if (sequence != undefined) {
|
|
66
|
+
return {
|
|
67
|
+
chrom: d.chrom,
|
|
68
|
+
start: d.startPos,
|
|
69
|
+
sequence,
|
|
70
|
+
};
|
|
71
|
+
} else {
|
|
72
|
+
console.log(
|
|
73
|
+
`No sequence found for interval ${d.chrom}:${d.startPos}-${d.endPos}`
|
|
74
|
+
);
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
})
|
|
76
78
|
);
|
|
77
79
|
|
|
78
|
-
|
|
79
|
-
this.publishData([features]);
|
|
80
|
-
}
|
|
80
|
+
this.publishData([features.filter((f) => f !== undefined)]);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
@@ -37,7 +37,7 @@ export default class TabixSource extends SingleAxisWindowedSource {
|
|
|
37
37
|
this.initializedPromise = new Promise((resolve) => {
|
|
38
38
|
Promise.all([
|
|
39
39
|
import("@gmod/tabix"),
|
|
40
|
-
import("generic-
|
|
40
|
+
import("generic-filehandle2"),
|
|
41
41
|
]).then(async ([{ TabixIndexedFile }, { RemoteFile }]) => {
|
|
42
42
|
const withBase = (/** @type {string} */ uri) =>
|
|
43
43
|
new RemoteFile(addBaseUrl(uri, this.view.getBaseUrl()));
|
package/dist/src/genomeSpy.d.ts
CHANGED
|
@@ -162,7 +162,7 @@ export default class GenomeSpy {
|
|
|
162
162
|
/**
|
|
163
163
|
* Events that are broadcasted to all views.
|
|
164
164
|
*/
|
|
165
|
-
export type BroadcastEventType = "dataFlowBuilt" | "
|
|
165
|
+
export type BroadcastEventType = "dataFlowBuilt" | "layout" | "layoutComputed" | "subtreeDataReady";
|
|
166
166
|
import { ViewFactory } from "./view/viewFactory.js";
|
|
167
167
|
import Animator from "./utils/animator.js";
|
|
168
168
|
import GenomeStore from "./genome/genomeStore.js";
|
|
@@ -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":"AAgDA;IACI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EA+FpD;IA5FG,uBAA0B;IAC1B,oDAAsB;IAItB,6BAA6B;IAC7B,uBADW,CAAC,MAAM,IAAI,CAAC,EAAE,CACM;IAE/B,sCAAsC;IACtC,wCAAgB;IAEhB,yBAAoC;IAEpC,4CAA4C;IAC5C,oBADW,CAAC,CAAS,IAAM,EAAN,MAAM,KAAE,MAAM,EAAE,CAAC,EAAE,CACZ;IAE5B,mBAAoD;IAEpD,0BAA0B;IAC1B,aADW,WAAW,CACM;IAE5B;;;;;OAKG;IACH,yBAFU,CAAC,IAAI,kCAAM,KAAK,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,GAAG,CAAC,MAAM,EAAE,CAAC,CAAS,IAAa,EAAb,aAAa,KAAE,IAAI,CAAC,EAAE,CAAC,CAEpB;IAEnC;;;;;;OAMG;IACH,iBAFU,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC,CAEhB;IAEhC;;;OAGG;IACH,0BAFU,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC,CAAC,CAEP;IAEzC,oFAAoF;IACpF,iBADW,MAAM,CAAC,MAAM,EAAE,OAAO,6BAA6B,EAAE,cAAc,CAAC,CAK9E;IAED,mBAAmB;IACnB,2CAAyB;IAEzB;;;;OAIG;IACH,eAFU,GAAG,mCAAO;QAAE,MAAM,EAAE,OAAO,wBAAwB,EAAE,iBAAiB,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAEtE;IAE9B;;OAEG;IACH,wBAFU,WAAW,CAEkB;IAEvC,oBAAoB;IACpB,kBADW,KAAK,CACiB;IAEjC,YAAkC;IA2CtC;;;OAGG;IACH,oCAFW,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,EAAE,QAIjC;IAED;;OAEG;IACH,+BAFW,MAAM,YAShB;IAED;;;;OAIG;IACH,sBAHW,MAAM,QACN,GAAG,EAAE,QAYf;IAED;;;;;OAKG;IACH,gBAHW,kBAAkB,YAClB,GAAG,QAQb;IAED;;;OAGG;IACH,iCAwDC;IA6DG,uBAOC;IAGD,mCAGE;IAOF,sCAEE;IAGF,iBAA0C;IAW9C;;OAEG;IACH,gBAuBC;IAED,sCAuKC;IAED;;;OAGG;IACH,UAFa,OAAO,CAAC,OAAO,CAAC,CA6B5B;IAED,4BAoMC;IA3Ke,iCAAoC;IA6KpD;;;OAGG;IACH,kBAHW,MAAM,KACN,MAAM,QAuEhB;IAED;;;;;;;OAOG;IACH,cAFa,CAAC,SAFH,CAAC,cACD,CAAS,IAAC,EAAD,CAAC,KAAE,OAAO,CAAC,MAAM,GAAG,WAAW,GAAG,OAAO,KAAK,EAAE,cAAc,CAAC,QAYlF;IAED;;;;;;;;OAQG;IACH,4BANW,MAAM,kBACN,MAAM,qBACN,MAAM,eACN,MAAM,UA0DhB;IAED,sBAqDC;IAED,kBAIC;IAED,iCAOC;IAED,iCASC;IAED,qFAWC;;CACJ;;;;iCAnhCY,eAAe,GAAG,QAAQ,GAAG,gBAAgB,GAAG,kBAAkB;4BAPnC,uBAAuB;qBAV9C,qBAAqB;wBAElB,yBAAyB;yCANR,yDAAyD;oBAUvD,oBAAoB;kBAP7C,wBAAwB;wBALnC,qBAAqB;oBAdR,uBAAuB;qBAStB,oBAAoB"}
|
package/dist/src/genomeSpy.js
CHANGED
|
@@ -10,7 +10,9 @@ import {
|
|
|
10
10
|
checkForDuplicateScaleNames,
|
|
11
11
|
setImplicitScaleNames,
|
|
12
12
|
calculateCanvasSize,
|
|
13
|
+
finalizeSubtreeGraphics,
|
|
13
14
|
} from "./view/viewUtils.js";
|
|
15
|
+
import { initializeViewSubtree, loadViewSubtreeData } from "./data/flowInit.js";
|
|
14
16
|
import UnitView from "./view/unitView.js";
|
|
15
17
|
|
|
16
18
|
import WebGLHelper, {
|
|
@@ -24,8 +26,6 @@ import InteractionEvent from "./utils/interactionEvent.js";
|
|
|
24
26
|
import Point from "./view/layout/point.js";
|
|
25
27
|
import Animator from "./utils/animator.js";
|
|
26
28
|
import DataFlow from "./data/dataFlow.js";
|
|
27
|
-
import { buildDataFlow } from "./view/flowBuilder.js";
|
|
28
|
-
import { optimizeDataFlow } from "./data/flowOptimizer.js";
|
|
29
29
|
import GenomeStore from "./genome/genomeStore.js";
|
|
30
30
|
import BmFontManager from "./fonts/bmFontManager.js";
|
|
31
31
|
import fasta from "./data/formats/fasta.js";
|
|
@@ -35,14 +35,13 @@ import refseqGeneTooltipHandler from "./tooltip/refseqGeneTooltipHandler.js";
|
|
|
35
35
|
import dataTooltipHandler from "./tooltip/dataTooltipHandler.js";
|
|
36
36
|
import { invalidatePrefix } from "./utils/propertyCacher.js";
|
|
37
37
|
import { VIEW_ROOT_NAME, ViewFactory } from "./view/viewFactory.js";
|
|
38
|
-
import { reconfigureScales } from "./view/scaleResolution.js";
|
|
39
38
|
import createBindingInputs from "./utils/inputBinding.js";
|
|
40
39
|
import { isStillZooming } from "./view/zoom.js";
|
|
41
40
|
import { createFramebufferInfo } from "twgl.js";
|
|
42
41
|
|
|
43
42
|
/**
|
|
44
43
|
* Events that are broadcasted to all views.
|
|
45
|
-
* @typedef {"dataFlowBuilt" | "
|
|
44
|
+
* @typedef {"dataFlowBuilt" | "layout" | "layoutComputed" | "subtreeDataReady"} BroadcastEventType
|
|
46
45
|
*/
|
|
47
46
|
|
|
48
47
|
vegaFormats("fasta", fasta);
|
|
@@ -229,7 +228,6 @@ export default class GenomeSpy {
|
|
|
229
228
|
}
|
|
230
229
|
|
|
231
230
|
namedSource.dataSource.updateDynamicData(data);
|
|
232
|
-
reconfigureScales(namedSource.hosts);
|
|
233
231
|
|
|
234
232
|
this.animator.requestRender();
|
|
235
233
|
}
|
|
@@ -517,6 +515,9 @@ export default class GenomeSpy {
|
|
|
517
515
|
highlightView: (view) => {
|
|
518
516
|
this.container.querySelector(".view-highlight")?.remove();
|
|
519
517
|
if (view) {
|
|
518
|
+
if (!view.isConfiguredVisible()) {
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
520
521
|
const coords = view.coords;
|
|
521
522
|
if (coords) {
|
|
522
523
|
const div = document.createElement("div");
|
|
@@ -572,42 +573,11 @@ export default class GenomeSpy {
|
|
|
572
573
|
this._glHelper.invalidateSize();
|
|
573
574
|
this.#setupDpr();
|
|
574
575
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
);
|
|
579
|
-
|
|
580
|
-
// Build the data flow based on the view hierarchy
|
|
581
|
-
const flow = buildDataFlow(this.viewRoot, context.dataFlow);
|
|
582
|
-
optimizeDataFlow(flow);
|
|
583
|
-
this.broadcast("dataFlowBuilt", flow);
|
|
584
|
-
|
|
585
|
-
// @ts-expect-error
|
|
586
|
-
if (import.meta.env?.DEV) {
|
|
587
|
-
flow.dataSources.forEach((ds) => console.log(ds.subtreeToString()));
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
// Create encoders (accessors, scales and related metadata)
|
|
591
|
-
unitViews.forEach((view) => view.mark.initializeEncoders());
|
|
592
|
-
|
|
593
|
-
// Compile shaders, create or load textures, etc.
|
|
594
|
-
const graphicsInitialized = Promise.all(
|
|
595
|
-
unitViews.map((view) => view.mark.initializeGraphics())
|
|
576
|
+
const { dataFlow, graphicsPromises } = initializeViewSubtree(
|
|
577
|
+
this.viewRoot,
|
|
578
|
+
context.dataFlow
|
|
596
579
|
);
|
|
597
|
-
|
|
598
|
-
for (const view of unitViews) {
|
|
599
|
-
flow.addObserver((collector) => {
|
|
600
|
-
view.mark.initializeData();
|
|
601
|
-
try {
|
|
602
|
-
// Update WebGL buffers
|
|
603
|
-
view.mark.updateGraphicsData();
|
|
604
|
-
} catch (e) {
|
|
605
|
-
e.view = view;
|
|
606
|
-
throw e;
|
|
607
|
-
}
|
|
608
|
-
context.animator.requestRender();
|
|
609
|
-
}, view);
|
|
610
|
-
}
|
|
580
|
+
this.broadcast("dataFlowBuilt", dataFlow);
|
|
611
581
|
|
|
612
582
|
// Have to wait until asynchronous font loading is complete.
|
|
613
583
|
// Text mark's geometry builder needs font metrics before data can be
|
|
@@ -615,28 +585,10 @@ export default class GenomeSpy {
|
|
|
615
585
|
// TODO: Make updateGraphicsData async and await font loading there.
|
|
616
586
|
await context.fontManager.waitUntilReady();
|
|
617
587
|
|
|
618
|
-
// Find all data sources and initiate loading
|
|
619
|
-
|
|
620
|
-
await Promise.all(
|
|
621
|
-
flow.dataSources.map((dataSource) => dataSource.load())
|
|
622
|
-
);
|
|
623
|
-
|
|
624
|
-
// Now that all data have been loaded, the domains may need adjusting
|
|
625
|
-
// IMPORTANT TODO: Check that discrete domains and indexers match!!!!!!!!!
|
|
626
|
-
reconfigureScales(this.viewRoot);
|
|
588
|
+
// Find all data sources and initiate loading.
|
|
589
|
+
await loadViewSubtreeData(this.viewRoot, new Set(dataFlow.dataSources));
|
|
627
590
|
|
|
628
|
-
|
|
629
|
-
// from the data once they are loaded.
|
|
630
|
-
// TODO: It would be great if this could be attached to the data flow,
|
|
631
|
-
// because now this is somewhat a hack and is incompatible with dynamic data
|
|
632
|
-
// loading in the future.
|
|
633
|
-
this.broadcast("dataLoaded");
|
|
634
|
-
|
|
635
|
-
await graphicsInitialized;
|
|
636
|
-
|
|
637
|
-
for (const view of unitViews) {
|
|
638
|
-
view.mark.finalizeGraphicsInitialization();
|
|
639
|
-
}
|
|
591
|
+
await finalizeSubtreeGraphics(graphicsPromises);
|
|
640
592
|
|
|
641
593
|
// Allow layout computation
|
|
642
594
|
// eslint-disable-next-line require-atomic-updates
|
|
@@ -872,6 +824,11 @@ export default class GenomeSpy {
|
|
|
872
824
|
canvas.addEventListener("dragstart", (event) =>
|
|
873
825
|
event.stopPropagation()
|
|
874
826
|
);
|
|
827
|
+
|
|
828
|
+
canvas.addEventListener("mouseout", () => {
|
|
829
|
+
this.tooltip.clear();
|
|
830
|
+
this._currentHover = null;
|
|
831
|
+
});
|
|
875
832
|
}
|
|
876
833
|
|
|
877
834
|
/**
|
|
@@ -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":"AAwZA;;;;GAIG;AACH,kCAJW,sBAAsB,gBACtB,WAAW,kBACX,WAAW;;;;;;EA8CrB;AAED;;;;;GAKG;AACH,0CALW,qBAAqB,WACrB,IAAI,CAAC,OAAO,SAAS,EAAE,cAAc,EAAE,KAAK,CAAC,OAC7C,MAAM,EAAE,GAAG,eAAe,YAC1B,YAAY,gBAYtB;AAED;;;;;;GAMG;AACH,qCALW,sBAAsB,mBACtB,OAAO,SAAS,EAAE,eAAe,KACjC,MAAM,KACN,MAAM,2BAWhB;AAED;;;;;GAKG;AACH,yCAJW,sBAAsB,mBACtB,OAAO,SAAS,EAAE,eAAe,SACjC,MAAM,UA4BhB;AAjfD;IACI;;;;;;;OAOG;IACH,uBANW,WAAW,eACX,MAAM;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAC,2BAGrC,sBAAsB,EAsFhC;IAnFG,wBAA2B;IAC3B;;;MAKO;IAEP,uCAAuC;IACvC,cADW,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CACN;IAE7B,6EAA6E;IAC7E,eADW,OAAO,CAAC,OAAO,qBAAqB,EAAE,SAAS,EAAE,YAAY,CAAC,CACvC;IAElC;;OAEG;IACH,mBAFU,OAAO,CAAC,OAAO,4BAA4B,EAAE,mBAAmB,EAAE,YAAY,CAAC,CAEnD;IA8CtC,0BAAoB;IACpB,2BAAY;IAGZ,oDAAoD;IACpD,2BADW,OAAO,SAAS,EAAE,iBAAiB,EAAE,CAQ/C;IACD,sDAGC;IAML,uBAGC;IAFG;;;MAAmC;IAIvC;;;;;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;;;MAS3C;IAED;;;OAGG;IACH;;;MAuBC;IAED;;;;;;;;;OASG;IACH,+BAHW,OAAO,4BAA4B,EAAE,OAAO,WAC5C,OAAO,QA0GjB;IAED;;OAEG;IACH,kCAFW,OAAO,4BAA4B,EAAE,mBAAmB,0BA+BlE;CACJ"}
|
|
@@ -90,6 +90,14 @@ export default class WebGLHelper {
|
|
|
90
90
|
|
|
91
91
|
addExtensionsToContext(gl);
|
|
92
92
|
|
|
93
|
+
// Make flat shading fast. All flat vertices have the same values, so
|
|
94
|
+
// it doesn't matter which one is the provoking vertex.
|
|
95
|
+
// https://registry.khronos.org/webgl/extensions/WEBGL_provoking_vertex/
|
|
96
|
+
const epv = gl.getExtension("WEBGL_provoking_vertex");
|
|
97
|
+
if (epv) {
|
|
98
|
+
epv.provokingVertexWEBGL(epv.FIRST_VERTEX_CONVENTION_WEBGL);
|
|
99
|
+
}
|
|
100
|
+
|
|
93
101
|
// Always use pre-multiplied alpha
|
|
94
102
|
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
|
95
103
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "in vec4 vColor;in float vSize;in float vNormalLengthInPixels;in float vGamma;out lowp vec4 fragColor;void main(void){float dpr=uDevicePixelRatio;float distance=abs(vNormalLengthInPixels);float opacity=clamp(((vSize/2.0-distance)*dpr),0.0,1.0);opacity=pow(opacity,vGamma);fragColor=vColor*opacity;if(uPickingEnabled){fragColor=vPickingColor;}}";
|
|
1
|
+
const shader = "flat in vec4 vColor;flat in float vSize;in float vNormalLengthInPixels;flat in float vGamma;out lowp vec4 fragColor;void main(void){float dpr=uDevicePixelRatio;float distance=abs(vNormalLengthInPixels);float opacity=clamp(((vSize/2.0-distance)*dpr),0.0,1.0);opacity=pow(opacity,vGamma);fragColor=vColor*opacity;if(uPickingEnabled){fragColor=vPickingColor;}}";
|
|
2
2
|
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "out vec4 vColor;out float vSize;out float vNormalLengthInPixels;out float vGamma;const int SHAPE_ARC=0;const int SHAPE_DOME=1;const int SHAPE_DIAGONAL=2;const int SHAPE_LINE=3;const int ORIENT_VERTICAL=0;const int ORIENT_HORIZONTAL=1;float distanceFromLine(vec2 pointOnLine1,vec2 pointOnLine2,vec2 point){vec2 a=point-pointOnLine1;vec2 b=pointOnLine2-pointOnLine1;vec2 proj=dot(a,b)/dot(b,b)*b;return length(a-proj);}bool isInsideViewport(vec2 point,float marginFactor){vec2 margin=uViewportSize*vec2(marginFactor);return point.x>=-margin.x&&point.x<=uViewportSize.x+margin.x&&point.y>=-margin.y&&point.y<=uViewportSize.y+margin.y;}void main(void){float pixelSize=1.0/uDevicePixelRatio;float opacity=getScaled_opacity()*uViewOpacity;vec2 p1,p2,p3,p4;vec2 a=applySampleFacet(vec2(getScaled_x(),getScaled_y()))*uViewportSize;vec2 b=applySampleFacet(vec2(getScaled_x2(),getScaled_y2()))*uViewportSize;if(uShape<=SHAPE_DOME){if(uShape==SHAPE_DOME){vec2 height=vec2(0.0);if(uOrient==ORIENT_VERTICAL){p1=vec2(min(a.x,b.x),b.y);p4=vec2(max(a.x,b.x),b.y);height=vec2(0.0,a.y-b.y);if(uClampApex){if(p4.x>0.0){p1.x=max(p1.x,-p4.x);}if(p1.x<uViewportSize.x){p4.x=min(p4.x,2.0*uViewportSize.x-p1.x);}}}else{p1=vec2(b.x,min(a.y,b.y));p4=vec2(b.x,max(a.y,b.y));height=vec2(a.x-b.x,0.0);if(uClampApex){if(p4.y>0.0){p1.y=max(p1.y,-p4.y);}if(p1.y<uViewportSize.y){p4.y=min(p4.y,2.0*uViewportSize.y-p1.y);}}}vec2 controlOffset=height/0.75;p2=p1+controlOffset;p3=p4+controlOffset;}if(uShape==SHAPE_ARC){p1=a;p4=b;vec2 chordVector=p4-p1;vec2 unitChordVector=normalize(chordVector);vec2 chordNormal=vec2(-unitChordVector.y,unitChordVector.x);float chordLength=length(chordVector);if(chordLength>uMaxChordLength){if(isInsideViewport(p1,2.0)){chordLength=uMaxChordLength;p4=p1+unitChordVector*uMaxChordLength;}else if(isInsideViewport(p4,2.0)){chordLength=uMaxChordLength;p1=p4-unitChordVector*uMaxChordLength;}}float height=max(chordLength/2.0*uArcHeightFactor,uMinArcHeight);vec2 controlOffset=chordNormal*height/0.75;p2=p1+controlOffset;p3=p4+controlOffset;}}else if(uShape==SHAPE_DIAGONAL){if(uOrient==ORIENT_VERTICAL){p1=a;p2=vec2(a.x,(a.y+b.y)/2.0);p3=vec2(b.x,(a.y+b.y)/2.0);p4=b;}else{p1=a;p2=vec2((a.x+b.x)/2.0,a.y);p3=vec2((a.x+b.x)/2.0,b.y);p4=b;}}else if(uShape==SHAPE_LINE){p1=a;p2=(a+b)/2.0;p3=p2;p4=b;}vec2 strip=vec2(float(gl_VertexID/2)/float(uSegmentBreaks),float(gl_VertexID % 2)-0.5);float t=smoothstep(0.0,1.0,strip.x);vec2 C1=p4-3.0*p3+3.0*p2-p1;vec2 C2=3.0*p3-6.0*p2+3.0*p1;vec2 C3=3.0*p2-3.0*p1;vec2 C4=p1;vec2 p;if(t==0.0){p=p1;}else if(t==1.0){p=p4;}else{p=C1*t*t*t+C2*t*t+C3*t+C4;}vec2 tangent=normalize(3.0*C1*t*t+2.0*C2*t+C3);vec2 normal=vec2(-tangent.y,tangent.x);float size=getScaled_size();if(size<pixelSize){opacity*=size/pixelSize;size=pixelSize;}float paddedSize=uPickingEnabled? max(size,uMinPickingSize): size+pixelSize;vNormalLengthInPixels=strip.y*paddedSize;if(uShape==SHAPE_ARC&&uArcFadingDistance[0]>0.0&&uArcFadingDistance[1]>0.0&&(!uNoFadingOnPointSelection||!isPointSelected())){float d=distanceFromLine(p1,p4,p);float distanceOpacity=smoothstep(uArcFadingDistance[1],uArcFadingDistance[0],d);opacity*=distanceOpacity;if(distanceOpacity<=0.0){vNormalLengthInPixels=0.0;}}p+=normal*vNormalLengthInPixels;gl_Position=pixelsToNdc(p);vec3 color=getScaled_color();vColor=vec4(color*opacity,opacity);vGamma=getGammaForColor(color);vSize=paddedSize;setupPicking();}";
|
|
1
|
+
const shader = "flat out vec4 vColor;flat out float vSize;out float vNormalLengthInPixels;flat out float vGamma;const int SHAPE_ARC=0;const int SHAPE_DOME=1;const int SHAPE_DIAGONAL=2;const int SHAPE_LINE=3;const int ORIENT_VERTICAL=0;const int ORIENT_HORIZONTAL=1;float distanceFromLine(vec2 pointOnLine1,vec2 pointOnLine2,vec2 point){vec2 a=point-pointOnLine1;vec2 b=pointOnLine2-pointOnLine1;vec2 proj=dot(a,b)/dot(b,b)*b;return length(a-proj);}bool isInsideViewport(vec2 point,float marginFactor){vec2 margin=uViewportSize*vec2(marginFactor);return point.x>=-margin.x&&point.x<=uViewportSize.x+margin.x&&point.y>=-margin.y&&point.y<=uViewportSize.y+margin.y;}void main(void){float pixelSize=1.0/uDevicePixelRatio;float opacity=getScaled_opacity()*uViewOpacity;vec2 p1,p2,p3,p4;vec2 a=applySampleFacet(vec2(getScaled_x(),getScaled_y()))*uViewportSize;vec2 b=applySampleFacet(vec2(getScaled_x2(),getScaled_y2()))*uViewportSize;if(uShape<=SHAPE_DOME){if(uShape==SHAPE_DOME){vec2 height=vec2(0.0);if(uOrient==ORIENT_VERTICAL){p1=vec2(min(a.x,b.x),b.y);p4=vec2(max(a.x,b.x),b.y);height=vec2(0.0,a.y-b.y);if(uClampApex){if(p4.x>0.0){p1.x=max(p1.x,-p4.x);}if(p1.x<uViewportSize.x){p4.x=min(p4.x,2.0*uViewportSize.x-p1.x);}}}else{p1=vec2(b.x,min(a.y,b.y));p4=vec2(b.x,max(a.y,b.y));height=vec2(a.x-b.x,0.0);if(uClampApex){if(p4.y>0.0){p1.y=max(p1.y,-p4.y);}if(p1.y<uViewportSize.y){p4.y=min(p4.y,2.0*uViewportSize.y-p1.y);}}}vec2 controlOffset=height/0.75;p2=p1+controlOffset;p3=p4+controlOffset;}if(uShape==SHAPE_ARC){p1=a;p4=b;vec2 chordVector=p4-p1;vec2 unitChordVector=normalize(chordVector);vec2 chordNormal=vec2(-unitChordVector.y,unitChordVector.x);float chordLength=length(chordVector);if(chordLength>uMaxChordLength){if(isInsideViewport(p1,2.0)){chordLength=uMaxChordLength;p4=p1+unitChordVector*uMaxChordLength;}else if(isInsideViewport(p4,2.0)){chordLength=uMaxChordLength;p1=p4-unitChordVector*uMaxChordLength;}}float height=max(chordLength/2.0*uArcHeightFactor,uMinArcHeight);vec2 controlOffset=chordNormal*height/0.75;p2=p1+controlOffset;p3=p4+controlOffset;}}else if(uShape==SHAPE_DIAGONAL){if(uOrient==ORIENT_VERTICAL){p1=a;p2=vec2(a.x,(a.y+b.y)/2.0);p3=vec2(b.x,(a.y+b.y)/2.0);p4=b;}else{p1=a;p2=vec2((a.x+b.x)/2.0,a.y);p3=vec2((a.x+b.x)/2.0,b.y);p4=b;}}else if(uShape==SHAPE_LINE){p1=a;p2=(a+b)/2.0;p3=p2;p4=b;}vec2 strip=vec2(float(gl_VertexID/2)/float(uSegmentBreaks),float(gl_VertexID % 2)-0.5);float t=smoothstep(0.0,1.0,strip.x);vec2 C1=p4-3.0*p3+3.0*p2-p1;vec2 C2=3.0*p3-6.0*p2+3.0*p1;vec2 C3=3.0*p2-3.0*p1;vec2 C4=p1;vec2 p;if(t==0.0){p=p1;}else if(t==1.0){p=p4;}else{p=C1*t*t*t+C2*t*t+C3*t+C4;}vec2 tangent=normalize(3.0*C1*t*t+2.0*C2*t+C3);vec2 normal=vec2(-tangent.y,tangent.x);float size=getScaled_size();if(size<pixelSize){opacity*=size/pixelSize;size=pixelSize;}float paddedSize=uPickingEnabled? max(size,uMinPickingSize): size+pixelSize;vNormalLengthInPixels=strip.y*paddedSize;if(uShape==SHAPE_ARC&&uArcFadingDistance[0]>0.0&&uArcFadingDistance[1]>0.0&&(!uNoFadingOnPointSelection||!isPointSelected())){float d=distanceFromLine(p1,p4,p);float distanceOpacity=smoothstep(uArcFadingDistance[1],uArcFadingDistance[0],d);opacity*=distanceOpacity;if(distanceOpacity<=0.0){vNormalLengthInPixels=0.0;}}p+=normal*vNormalLengthInPixels;gl_Position=pixelsToNdc(p);vec3 color=getScaled_color();vColor=vec4(color*opacity,opacity);vGamma=getGammaForColor(color);vSize=paddedSize;setupPicking();}";
|
|
2
2
|
export default shader;
|
package/dist/src/marks/mark.d.ts
CHANGED
|
@@ -200,6 +200,7 @@ export default class Mark<P extends import("../spec/mark.js").MarkProps = import
|
|
|
200
200
|
* Delete WebGL buffers etc.
|
|
201
201
|
*/
|
|
202
202
|
deleteGraphicsData(): void;
|
|
203
|
+
dispose(): void;
|
|
203
204
|
/**
|
|
204
205
|
*
|
|
205
206
|
* @param {any} vertexData TODO: Extract type from VertexBuilder
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":"AA0DA,mCAAoC,sBAAsB,CAAC;AAC3D,mCAAoC,sBAAsB,CAAC;AAE3D,uCAAwC,oBAAoB,CAAC;AAE7D;;;;;;;;;;;;;GAaG;AAEH;;GAEG;AACH,0BAF0B,CAAC,SAAd,mCAAW;
|
|
1
|
+
{"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../src/marks/mark.js"],"names":[],"mappings":"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"}
|
package/dist/src/marks/mark.js
CHANGED
|
@@ -95,6 +95,11 @@ export default class Mark {
|
|
|
95
95
|
*/
|
|
96
96
|
#callAfterShaderCompilation = [];
|
|
97
97
|
|
|
98
|
+
/**
|
|
99
|
+
* @type {{expr: import("../view/paramMediator.js").ExprRefFunction, listener: () => void}[]}
|
|
100
|
+
*/
|
|
101
|
+
#exprListeners = [];
|
|
102
|
+
|
|
98
103
|
/**
|
|
99
104
|
* @param {import("../view/unitView.js").default} unitView
|
|
100
105
|
*/
|
|
@@ -1034,6 +1039,7 @@ export default class Mark {
|
|
|
1034
1039
|
|
|
1035
1040
|
// Register a listener ...
|
|
1036
1041
|
fn.addListener(set);
|
|
1042
|
+
this.#exprListeners.push({ expr: fn, listener: set });
|
|
1037
1043
|
// ... and set the initial value
|
|
1038
1044
|
set();
|
|
1039
1045
|
} else {
|
|
@@ -1045,7 +1051,14 @@ export default class Mark {
|
|
|
1045
1051
|
* Delete WebGL buffers etc.
|
|
1046
1052
|
*/
|
|
1047
1053
|
deleteGraphicsData() {
|
|
1048
|
-
const
|
|
1054
|
+
const glHelper = this.glHelper;
|
|
1055
|
+
if (!glHelper) {
|
|
1056
|
+
this.vertexArrayInfo = undefined;
|
|
1057
|
+
this.bufferInfo = undefined;
|
|
1058
|
+
return;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
const gl = glHelper.gl;
|
|
1049
1062
|
|
|
1050
1063
|
if (this.vertexArrayInfo) {
|
|
1051
1064
|
this.gl.bindVertexArray(null);
|
|
@@ -1070,6 +1083,14 @@ export default class Mark {
|
|
|
1070
1083
|
}
|
|
1071
1084
|
}
|
|
1072
1085
|
|
|
1086
|
+
dispose() {
|
|
1087
|
+
for (const { expr, listener } of this.#exprListeners) {
|
|
1088
|
+
expr.removeListener(listener);
|
|
1089
|
+
}
|
|
1090
|
+
this.#exprListeners.length = 0;
|
|
1091
|
+
this.deleteGraphicsData();
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1073
1094
|
/**
|
|
1074
1095
|
*
|
|
1075
1096
|
* @param {any} vertexData TODO: Extract type from VertexBuilder
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "const lowp vec4 white=vec4(1.0);const lowp vec4 black=vec4(0.0,0.0,0.0,1.0);in float vRadius;in float vRadiusWithPadding;in lowp vec4 vFillColor;in lowp vec4 vStrokeColor;in lowp float vShape;in lowp float vHalfStrokeWidth;in mat2 vRotationMatrix;out lowp vec4 fragColor;const float CIRCLE=0.0;const float SQUARE=1.0;const float CROSS=2.0;const float DIAMOND=3.0;const float TRIANGLE_UP=4.0;const float TICK_UP=8.0;float circle(vec2 p,float r){return length(p)-r;}float square(vec2 p,float r){p=abs(p);return max(p.x,p.y)-r;}float tickUp(vec2 p,float r){float halfR=r*0.5;p.y+=halfR;p=abs(p);return max(p.x-r*0.15,p.y-halfR);}float equilateralTriangle(vec2 p,float r){p.y=-p.y;float k=sqrt(3.0);float kr=k*r;p.y-=kr/2.0;return max((abs(p.x)*k+p.y)/2.0,-p.y-kr);}float crossShape(vec2 p,float r){p=abs(p);vec2 b=vec2(0.4,1.0)*r;vec2 v=abs(p)-b.xy;vec2 h=abs(p)-b.yx;return min(max(v.x,v.y),max(h.x,h.y));}float diamond(vec2 p,float r){p=abs(p);return(max(abs(p.x-p.y),abs(p.x+p.y))-r)/sqrt(2.0);}void main(){float d;vec2 p=vRotationMatrix*(2.0*gl_PointCoord-1.0)*vRadiusWithPadding;float r=vRadius;if(vShape==CIRCLE){d=circle(p,r);}else if(vShape==SQUARE){d=square(p,r);}else if(vShape==CROSS){d=crossShape(p,r);}else if(vShape==DIAMOND){d=diamond(p,r);}else if(vShape==TRIANGLE_UP){d=equilateralTriangle(p,r);}else if(vShape==TICK_UP){d=tickUp(p,r);}else{d=0.0;}if(!uPickingEnabled){lowp vec4 fillColor=mix(vFillColor,white,-d*uGradientStrength/vRadius);fragColor=distanceToColor(d+(uInwardStroke ? vHalfStrokeWidth : 0.0),fillColor,vStrokeColor,vec4(0.0),vHalfStrokeWidth);}else if(d-vHalfStrokeWidth<=0.0){fragColor=vPickingColor;}else{discard;}}";
|
|
1
|
+
const shader = "const lowp vec4 white=vec4(1.0);const lowp vec4 black=vec4(0.0,0.0,0.0,1.0);flat in float vRadius;flat in float vRadiusWithPadding;flat in lowp vec4 vFillColor;flat in lowp vec4 vStrokeColor;flat in lowp float vShape;flat in lowp float vHalfStrokeWidth;flat in mat2 vRotationMatrix;out lowp vec4 fragColor;const float CIRCLE=0.0;const float SQUARE=1.0;const float CROSS=2.0;const float DIAMOND=3.0;const float TRIANGLE_UP=4.0;const float TICK_UP=8.0;float circle(vec2 p,float r){return length(p)-r;}float square(vec2 p,float r){p=abs(p);return max(p.x,p.y)-r;}float tickUp(vec2 p,float r){float halfR=r*0.5;p.y+=halfR;p=abs(p);return max(p.x-r*0.15,p.y-halfR);}float equilateralTriangle(vec2 p,float r){p.y=-p.y;float k=sqrt(3.0);float kr=k*r;p.y-=kr/2.0;return max((abs(p.x)*k+p.y)/2.0,-p.y-kr);}float crossShape(vec2 p,float r){p=abs(p);vec2 b=vec2(0.4,1.0)*r;vec2 v=abs(p)-b.xy;vec2 h=abs(p)-b.yx;return min(max(v.x,v.y),max(h.x,h.y));}float diamond(vec2 p,float r){p=abs(p);return(max(abs(p.x-p.y),abs(p.x+p.y))-r)/sqrt(2.0);}void main(){float d;vec2 p=vRotationMatrix*(2.0*gl_PointCoord-1.0)*vRadiusWithPadding;float r=vRadius;if(vShape==CIRCLE){d=circle(p,r);}else if(vShape==SQUARE){d=square(p,r);}else if(vShape==CROSS){d=crossShape(p,r);}else if(vShape==DIAMOND){d=diamond(p,r);}else if(vShape==TRIANGLE_UP){d=equilateralTriangle(p,r);}else if(vShape==TICK_UP){d=tickUp(p,r);}else{d=0.0;}if(!uPickingEnabled){lowp vec4 fillColor=mix(vFillColor,white,-d*uGradientStrength/vRadius);fragColor=distanceToColor(d+(uInwardStroke ? vHalfStrokeWidth : 0.0),fillColor,vStrokeColor,vec4(0.0),vHalfStrokeWidth);}else if(d-vHalfStrokeWidth<=0.0){fragColor=vPickingColor;}else{discard;}}";
|
|
2
2
|
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "out float vRadius;out float vRadiusWithPadding;out lowp vec4 vFillColor;out lowp vec4 vStrokeColor;out lowp float vShape;out lowp float vHalfStrokeWidth;out mat2 vRotationMatrix;const float CIRCLE=0.0;const float SQUARE=1.0;const float CROSS=2.0;const float DIAMOND=3.0;const float TRIANGLE_UP=4.0;const float TRIANGLE_RIGHT=5.0;const float TRIANGLE_DOWN=6.0;const float TRIANGLE_LEFT=7.0;const float TICK_UP=8.0;const float TICK_RIGHT=9.0;const float TICK_DOWN=10.0;const float TICK_LEFT=11.0;float computeSemanticThresholdFactor(){return getScaled_semanticScore()>=uSemanticThreshold ? 1.0 : 0.0;}vec2 getDxDy(){\n#if defined(dx_DEFINED) || defined(dy_DEFINED)\nreturn vec2(getScaled_dx(),getScaled_dy())/uViewportSize;\n#else\nreturn vec2(0.0,0.0);\n#endif\n}void main(void){float shapeAngle=0.0;float semanticThresholdFactor=isPointSelected()? 1.0: computeSemanticThresholdFactor();if(semanticThresholdFactor<=0.0){gl_PointSize=0.0;gl_Position=vec4(100.0,0.0,0.0,0.0);return;}float size=getScaled_size();vec2 pos=vec2(getScaled_x(),getScaled_y())+getDxDy();gl_Position=unitToNdc(applySampleFacet(pos));float strokeWidth=getScaled_strokeWidth();float diameter=sqrt(size)*uScaleFactor*semanticThresholdFactor;float opacity=uViewOpacity;if(strokeWidth<=0.0||uInwardStroke){float minDiameter=1.0/uDevicePixelRatio;if(diameter<minDiameter){opacity*=pow(diameter/minDiameter,2.5);diameter=minDiameter;}}float fillOpa=getScaled_fillOpacity()*opacity;float strokeOpa=getScaled_strokeOpacity()*opacity;vShape=getScaled_shape();bool circle=vShape==0.0;if(vShape>TICK_UP&&vShape<=TICK_LEFT){shapeAngle=(vShape-TICK_UP)*90.0;vShape=TICK_UP;}else if(vShape>TRIANGLE_UP&&vShape<=TRIANGLE_LEFT){shapeAngle=(vShape-TRIANGLE_UP)*90.0;vShape=TRIANGLE_UP;}float angleInDegrees=getScaled_angle();float angle=-(shapeAngle+angleInDegrees)*PI/180.0;float sinTheta=sin(angle);float cosTheta=cos(angle);vRotationMatrix=mat2(cosTheta,sinTheta,-sinTheta,cosTheta);float roomForRotation=circle ? 1.0 : sin(mod(angle,PI/2.0)+PI/4.0)/sin(PI/4.0);float aaPadding=1.0/uDevicePixelRatio;float rotationPadding=(diameter*roomForRotation)-diameter;float strokePadding=uInwardStroke ? 0.0 : strokeWidth*(circle ? 1.0 : sqrt(3.0));float padding=rotationPadding+strokePadding+aaPadding;gl_PointSize=max((diameter+padding),uPickingEnabled ? uMinPickingSize : 0.0)*uDevicePixelRatio;vRadius=diameter/2.0;vRadiusWithPadding=vRadius+padding/2.0;vHalfStrokeWidth=strokeWidth/2.0;vFillColor=vec4(getScaled_fill()*fillOpa,fillOpa);vStrokeColor=vec4(getScaled_stroke()*strokeOpa,strokeOpa);setupPicking();}";
|
|
1
|
+
const shader = "flat out float vRadius;flat out float vRadiusWithPadding;flat out lowp vec4 vFillColor;flat out lowp vec4 vStrokeColor;flat out lowp float vShape;flat out lowp float vHalfStrokeWidth;flat out mat2 vRotationMatrix;const float CIRCLE=0.0;const float SQUARE=1.0;const float CROSS=2.0;const float DIAMOND=3.0;const float TRIANGLE_UP=4.0;const float TRIANGLE_RIGHT=5.0;const float TRIANGLE_DOWN=6.0;const float TRIANGLE_LEFT=7.0;const float TICK_UP=8.0;const float TICK_RIGHT=9.0;const float TICK_DOWN=10.0;const float TICK_LEFT=11.0;float computeSemanticThresholdFactor(){return getScaled_semanticScore()>=uSemanticThreshold ? 1.0 : 0.0;}vec2 getDxDy(){\n#if defined(dx_DEFINED) || defined(dy_DEFINED)\nreturn vec2(getScaled_dx(),getScaled_dy())/uViewportSize;\n#else\nreturn vec2(0.0,0.0);\n#endif\n}void main(void){float shapeAngle=0.0;float semanticThresholdFactor=isPointSelected()? 1.0: computeSemanticThresholdFactor();if(semanticThresholdFactor<=0.0){gl_PointSize=0.0;gl_Position=vec4(100.0,0.0,0.0,0.0);return;}float size=getScaled_size();vec2 pos=vec2(getScaled_x(),getScaled_y())+getDxDy();gl_Position=unitToNdc(applySampleFacet(pos));float strokeWidth=getScaled_strokeWidth();float diameter=sqrt(size)*uScaleFactor*semanticThresholdFactor;float opacity=uViewOpacity;if(strokeWidth<=0.0||uInwardStroke){float minDiameter=1.0/uDevicePixelRatio;if(diameter<minDiameter){opacity*=pow(diameter/minDiameter,2.5);diameter=minDiameter;}}float fillOpa=getScaled_fillOpacity()*opacity;float strokeOpa=getScaled_strokeOpacity()*opacity;vShape=getScaled_shape();bool circle=vShape==0.0;if(vShape>TICK_UP&&vShape<=TICK_LEFT){shapeAngle=(vShape-TICK_UP)*90.0;vShape=TICK_UP;}else if(vShape>TRIANGLE_UP&&vShape<=TRIANGLE_LEFT){shapeAngle=(vShape-TRIANGLE_UP)*90.0;vShape=TRIANGLE_UP;}float angleInDegrees=getScaled_angle();float angle=-(shapeAngle+angleInDegrees)*PI/180.0;float sinTheta=sin(angle);float cosTheta=cos(angle);vRotationMatrix=mat2(cosTheta,sinTheta,-sinTheta,cosTheta);float roomForRotation=circle ? 1.0 : sin(mod(angle,PI/2.0)+PI/4.0)/sin(PI/4.0);float aaPadding=1.0/uDevicePixelRatio;float rotationPadding=(diameter*roomForRotation)-diameter;float strokePadding=uInwardStroke ? 0.0 : strokeWidth*(circle ? 1.0 : sqrt(3.0));float padding=rotationPadding+strokePadding+aaPadding;gl_PointSize=max((diameter+padding),uPickingEnabled ? uMinPickingSize : 0.0)*uDevicePixelRatio;vRadius=diameter/2.0;vRadiusWithPadding=vRadius+padding/2.0;vHalfStrokeWidth=strokeWidth/2.0;vFillColor=vec4(getScaled_fill()*fillOpa,fillOpa);vStrokeColor=vec4(getScaled_stroke()*strokeOpa,strokeOpa);setupPicking();}";
|
|
2
2
|
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\nin vec2 vPosInPixels;\n#endif\
|
|
1
|
+
const shader = "#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\nin vec2 vPosInPixels;\n#endif\nflat in vec2 vHalfSizeInPixels;flat in lowp vec4 vFillColor;flat in lowp vec4 vStrokeColor;flat in float vHalfStrokeWidth;flat in vec4 vCornerRadii;out lowp vec4 fragColor;\n#ifdef SHADOW\nfloat gaussian(float x,float sigma){const float pi=3.141592653589793;return exp(-(x*x)/(2.0*sigma*sigma))/(sqrt(2.0*pi)*sigma);}vec2 erf(vec2 x){vec2 s=sign(x),a=abs(x);x=1.0+(0.278393+(0.230389+0.078108*(a*a))*a)*a;x*=x;return s-s/(x*x);}float roundedBoxShadowX(float x,float y,float sigma,float corner,vec2 halfSize){float delta=min(halfSize.y-corner-abs(y),0.0);float curved=halfSize.x-corner+sqrt(max(0.0,corner*corner-delta*delta));vec2 integral=0.5+0.5*erf((x+vec2(-curved,curved))*(sqrt(0.5)/sigma));return integral.y-integral.x;}float roundedBoxShadow(vec2 lower,vec2 upper,vec2 point,float sigma,float corner){vec2 center=(lower+upper)*0.5;vec2 halfSize=(upper-lower)*0.5;point-=center;float low=point.y-halfSize.y;float high=point.y+halfSize.y;float start=clamp(-3.0*sigma,low,high);float end=clamp(3.0*sigma,low,high);float step=(end-start)/4.0;float y=start+step*0.5;float value=0.0;for(int i=0;i<4;i++){value+=roundedBoxShadowX(point.x,point.y-y,sigma,corner,halfSize)*gaussian(y,sigma)*step;y+=step;}return value;}\n#endif\nfloat sdRoundedBox(vec2 p,vec2 b,vec4 r){r.xy=p.x>0.0 ? r.xy : r.zw;r.x=p.y>0.0 ? r.x : r.y;vec2 q=abs(p)-b+r.x;return min(max(q.x,q.y),0.0)+length(max(q,0.0))-r.x;}float sdSharpBox(vec2 p,vec2 b){vec2 q=abs(p)-b;return max(q.x,q.y);}float diagonalPattern(vec2 uv,float spacing){float divisor=spacing*vHalfStrokeWidth*2.0*1.5;return abs(mod(uv.x-uv.y,divisor)-0.5*divisor)/1.5;}float verticalPattern(float x,float spacing){float divisor=spacing*vHalfStrokeWidth*2.0;return abs(mod(x,divisor))/2.0;}float circle(vec2 p,float r){return length(p)-r;}float masonryCirclePattern(vec2 uv,float spacing,float radius){float halfSpacing=0.5*spacing;float row=floor(uv.y/spacing);float shift=mod(row,2.0)*halfSpacing;vec2 shifted=vec2(uv.x+shift,uv.y+halfSpacing);vec2 cell=mod(shifted+0.5*spacing,spacing)-halfSpacing;return abs(circle(cell,radius));}/***Patterns:*0 none*1 diagonal(/)*2 antiDiagonal(\\)*3 cross(X)*4 vertical(|)*5 horizontal(-)*6 grid(+)*7 dots(.)*8 rings(o)*9 ringsLarge(O)*/float pattern(){\n#ifdef STROKED\nint patternType=uHatchPattern;vec2 uv=vPosInPixels;float spacing=4.0;switch(patternType){case 1:return diagonalPattern(vec2(uv.x,-uv.y),spacing);case 2:return diagonalPattern(uv,spacing);case 3:return min(diagonalPattern(uv,spacing),diagonalPattern(vec2(uv.x,-uv.y),spacing));case 4:return verticalPattern(uv.x,spacing);case 5:return verticalPattern(uv.y,spacing);case 6:return min(verticalPattern(uv.x,spacing),verticalPattern(uv.y,spacing));case 7:case 8:case 9:{float spacing=vHalfStrokeWidth*14.0;float radius=spacing*(patternType==8 ? 0.2 :patternType==9 ? 0.35 :0.07);return masonryCirclePattern(uv,spacing,radius);}default:break;}\n#endif\nreturn 1.0/0.0;}void main(void){\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\n#ifdef ROUNDED_CORNERS\nfloat d=sdRoundedBox(vPosInPixels,vHalfSizeInPixels,vCornerRadii);\n#else\nfloat d=sdSharpBox(vPosInPixels,vHalfSizeInPixels);\n#endif\nvec4 backgroundColor=vec4(0.0,0.0,0.0,0.0);\n#ifdef SHADOW\nfloat maxCornerRadius=max(vCornerRadii.x,max(vCornerRadii.y,max(vCornerRadii.z,vCornerRadii.w)));float shadow=0.0;if(d>=vHalfStrokeWidth-1.0&&uShadowOpacity>0.0){shadow=roundedBoxShadow(-vHalfSizeInPixels-vHalfStrokeWidth,vHalfSizeInPixels+vHalfStrokeWidth,vPosInPixels-vec2(uShadowOffsetX,-uShadowOffsetY),max(uShadowBlur/2.5,0.25),maxCornerRadius+vHalfStrokeWidth)*uShadowOpacity*uViewOpacity;}backgroundColor=vec4(uShadowColor*shadow,shadow);\n#endif\nif(vHalfStrokeWidth>0.0&&uHatchPattern>0){d=max(d,-pattern());}fragColor=distanceToColor(d,vFillColor,vStrokeColor,backgroundColor,vHalfStrokeWidth);if(uPickingEnabled){if(d<vHalfStrokeWidth){fragColor=vPickingColor;}}else if(fragColor.a==0.0){discard;}\n#else\nfragColor=vFillColor;if(uPickingEnabled){fragColor=vPickingColor;}\n#endif\n}";
|
|
2
2
|
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "out lowp vec4 vFillColor;out lowp vec4 vStrokeColor;out float vHalfStrokeWidth;out vec4 vCornerRadii;\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\nout vec2 vPosInPixels;\n#endif\
|
|
1
|
+
const shader = "flat out lowp vec4 vFillColor;flat out lowp vec4 vStrokeColor;flat out float vHalfStrokeWidth;flat out vec4 vCornerRadii;\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\nout vec2 vPosInPixels;\n#endif\nflat out vec2 vHalfSizeInPixels;/***Adjusts the vertex position to ensure that the rectangle is at least `minSpan`*wide or high. Returns a value that reflects the amount of clamping and can be*used to adjust the opacity of the rectangle.**pos: vertex position*frac: vertex position within the rectangle,[0,1]*size: width or height of the rectangle*minSize: minimum width or height of the rectangle*/float clampMinSize(inout float pos,float frac,float size,float minSize){if(minSize>0.0&&size<minSize){pos+=(frac-0.5)*(minSize-size);return size/minSize;}return 1.0;}void sort(inout float a,inout float b){if(a>b){float tmp=b;b=a;a=tmp;}}/***The vertex position wrt the rectangle specified by(x,x2,y,y2).*[0,0]=[x,y],[1,1]=[x2,y2].*The x or y component may contain fractional values if the rectangle*have been tessellated.*/vec2 getVertexPos(){int index=gl_VertexID % 6;return vec2(index==0||index==1||index==3 ? 0.0 : 1.0,index==0||index==1||index==2 ? 0.0 : 1.0);}void main(void){vec2 frac=getVertexPos();vec2 normalizedMinSize=vec2(uMinWidth,uMinHeight)/uViewportSize;vec4 cornerRadii=vec4(uCornerRadiusTopRight,uCornerRadiusBottomRight,uCornerRadiusTopLeft,uCornerRadiusBottomLeft);float x=getScaled_x();float x2=getScaled_x2();float y=getScaled_y();float y2=getScaled_y2();sort(x,x2);sort(y,y2);float clampMargin=1.0;vec2 pos1=vec2(clamp(x,0.0-clampMargin,1.0+clampMargin),y);vec2 pos2=vec2(clamp(x2,0.0-clampMargin,1.0+clampMargin),y2);vec2 size=pos2-pos1;if(size.x<=0.0||size.y<=0.0){gl_Position=vec4(0.0,0.0,0.0,1.0);return;}vec2 pos=pos1+frac*size;size.y*=getSampleFacetHeight(pos);float opaFactor=uViewOpacity*max(uMinOpacity,clampMinSize(pos.x,frac.x,size.x,normalizedMinSize.x)*clampMinSize(pos.y,frac.y,size.y,normalizedMinSize.y));size=max(size,normalizedMinSize);pos=applySampleFacet(pos);\n#if defined(ROUNDED_CORNERS) || defined(STROKED) || defined(SHADOW)\nfloat aaPadding=1.0/uDevicePixelRatio;float shadowPadding=uShadowBlur+max(abs(uShadowOffsetX),abs(uShadowOffsetY));float strokeWidth=getScaled_strokeWidth();float strokeOpacity=getScaled_strokeOpacity()*opaFactor;vec2 centeredFrac=frac-0.5;vec2 expand=centeredFrac*(strokeWidth+aaPadding+shadowPadding*2.0)/uViewportSize;pos+=expand;vec2 sizeInPixels=size*uViewportSize;vPosInPixels=(centeredFrac+expand/size)*sizeInPixels;vHalfSizeInPixels=sizeInPixels/2.0;vCornerRadii=min(cornerRadii,min(vHalfSizeInPixels.x,vHalfSizeInPixels.y));vHalfStrokeWidth=strokeWidth/2.0;vStrokeColor=vec4(getScaled_stroke()*strokeOpacity,strokeOpacity);\n#endif\ngl_Position=unitToNdc(pos);float fillOpacity=getScaled_fillOpacity()*opaFactor;vFillColor=vec4(getScaled_fill()*fillOpacity,fillOpacity);setupPicking();}";
|
|
2
2
|
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "const int BUTT=0;const int SQUARE=1;const int ROUND=2;uniform sampler2D uDashTexture;in vec4 vColor;in float vSize;in vec2 vPosInPixels;in float vNormalLengthInPixels;out lowp vec4 fragColor;void main(void){float dpr=uDevicePixelRatio;float distanceFromEnd=-min(vPosInPixels[0],vPosInPixels[1]);float distance;if(distanceFromEnd>0.0&&uStrokeCap==ROUND){distance=length(vec2(distanceFromEnd,vNormalLengthInPixels));}else{distance=abs(vNormalLengthInPixels);}float opacity=clamp(((vSize/2.0-distance)*dpr),-0.5,0.5)+0.5;if(uDashTextureSize>0.0){float pos=(vPosInPixels[0]+uStrokeDashOffset)*dpr;float floored=floor(pos);vec2 texelPositions=(floored+vec2(0.5,1.5))/dpr/uDashTextureSize;opacity*=mix(texture(uDashTexture,vec2(texelPositions[0],0)).r,texture(uDashTexture,vec2(texelPositions[1],0)).r,clamp((pos-floored),0.0,1.0));}fragColor=vColor*opacity;if(uPickingEnabled){fragColor=vPickingColor;}}";
|
|
1
|
+
const shader = "const int BUTT=0;const int SQUARE=1;const int ROUND=2;uniform sampler2D uDashTexture;flat in vec4 vColor;flat in float vSize;in vec2 vPosInPixels;in float vNormalLengthInPixels;out lowp vec4 fragColor;void main(void){float dpr=uDevicePixelRatio;float distanceFromEnd=-min(vPosInPixels[0],vPosInPixels[1]);float distance;if(distanceFromEnd>0.0&&uStrokeCap==ROUND){distance=length(vec2(distanceFromEnd,vNormalLengthInPixels));}else{distance=abs(vNormalLengthInPixels);}float opacity=clamp(((vSize/2.0-distance)*dpr),-0.5,0.5)+0.5;if(uDashTextureSize>0.0){float pos=(vPosInPixels[0]+uStrokeDashOffset)*dpr;float floored=floor(pos);vec2 texelPositions=(floored+vec2(0.5,1.5))/dpr/uDashTextureSize;opacity*=mix(texture(uDashTexture,vec2(texelPositions[0],0)).r,texture(uDashTexture,vec2(texelPositions[1],0)).r,clamp((pos-floored),0.0,1.0));}fragColor=vColor*opacity;if(uPickingEnabled){fragColor=vPickingColor;}}";
|
|
2
2
|
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "const int BUTT=0;const int SQUARE=1;const int ROUND=2;in float pos;in float side;out vec4 vColor;out float vSize;out float vNormalLengthInPixels;out highp vec2 vPosInPixels;void main(void){float pixelSize=1.0/uDevicePixelRatio;float size=getScaled_size();float opacity=getScaled_opacity()*uViewOpacity;if(size<pixelSize){opacity*=size/pixelSize;size=pixelSize;}vec2 a=applySampleFacet(vec2(getScaled_x(),getScaled_y()));vec2 b=applySampleFacet(vec2(getScaled_x2(),getScaled_y2()));vec2 tangent=b-a;float offset=0.0;float relativeDiff=0.0;if(uMinLength>0.0||uStrokeCap!=BUTT){float len=length(tangent*uViewportSize);float diff=max(0.0,uMinLength-len);if(uStrokeCap!=BUTT){diff+=size;}relativeDiff=diff/len;offset=relativeDiff*(pos-0.5);}vec2 p=pos<1.0? a+tangent*(pos+offset): b+tangent*offset;float aaPadding=pixelSize;vec2 normal=normalize(vec2(-tangent.y,tangent.x)/uViewportSize);p+=normal*side*(size+aaPadding)/uViewportSize;gl_Position=unitToNdc(p);vColor=vec4(getScaled_color()*opacity,opacity);vSize=size;vNormalLengthInPixels=side*(size+aaPadding);vPosInPixels=vec2(pos,(1.0-pos))*(1.0+relativeDiff)*length(tangent*uViewportSize)-vec2(uStrokeCap!=BUTT ? size/2.0 : 0.0);setupPicking();}";
|
|
1
|
+
const shader = "const int BUTT=0;const int SQUARE=1;const int ROUND=2;in float pos;in float side;flat out vec4 vColor;flat out float vSize;out float vNormalLengthInPixels;out highp vec2 vPosInPixels;void main(void){float pixelSize=1.0/uDevicePixelRatio;float size=getScaled_size();float opacity=getScaled_opacity()*uViewOpacity;if(size<pixelSize){opacity*=size/pixelSize;size=pixelSize;}vec2 a=applySampleFacet(vec2(getScaled_x(),getScaled_y()));vec2 b=applySampleFacet(vec2(getScaled_x2(),getScaled_y2()));vec2 tangent=b-a;float offset=0.0;float relativeDiff=0.0;if(uMinLength>0.0||uStrokeCap!=BUTT){float len=length(tangent*uViewportSize);float diff=max(0.0,uMinLength-len);if(uStrokeCap!=BUTT){diff+=size;}relativeDiff=diff/len;offset=relativeDiff*(pos-0.5);}vec2 p=pos<1.0? a+tangent*(pos+offset): b+tangent*offset;float aaPadding=pixelSize;vec2 normal=normalize(vec2(-tangent.y,tangent.x)/uViewportSize);p+=normal*side*(size+aaPadding)/uViewportSize;gl_Position=unitToNdc(p);vColor=vec4(getScaled_color()*opacity,opacity);vSize=size;vNormalLengthInPixels=side*(size+aaPadding);vPosInPixels=vec2(pos,(1.0-pos))*(1.0+relativeDiff)*length(tangent*uViewportSize)-vec2(uStrokeCap!=BUTT ? size/2.0 : 0.0);setupPicking();}";
|
|
2
2
|
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "uniform sampler2D uTexture;in vec2 vTexCoord;in float vEdgeFadeOpacity;in vec4 vColor;in float vSlope;in float vGamma;out lowp vec4 fragColor;float median(float r,float g,float b){return max(min(r,g),min(max(r,g),b));}
|
|
1
|
+
const shader = "uniform sampler2D uTexture;in vec2 vTexCoord;in float vEdgeFadeOpacity;flat in vec4 vColor;flat in float vSlope;flat in float vGamma;out lowp vec4 fragColor;float median(float r,float g,float b){return max(min(r,g),min(max(r,g),b));}float getDist(vec2 uv){vec3 c=texture(uTexture,uv).rgb;return 1.0-median(c.r,c.g,c.b);}/***Calculates the super-sampled distance to the edge.*This is used to avoid aliasing when rendering small text,*as mip-mapping cannot be used here.*The distance is averaged over a grid of n x n samples.*/float getSuperDist(vec2 uv){vec2 dx=dFdx(uv);vec2 dy=dFdy(uv);float n=2.0;float sum=0.0;for(float x=0.5;x<n;x++){for(float y=0.5;y<n;y++){sum+=getDist(uv+x/n*dx+y/n*dy);}}return sum/(n*n);}void main(){float sigDist=getSuperDist(vTexCoord);float slope=vSlope;if(uLogoLetter){slope=0.7/length(vec2(dFdy(sigDist),dFdx(sigDist)));}float opa=clamp((sigDist-0.5)*slope+0.5,0.0,1.0);opa*=clamp(vEdgeFadeOpacity,0.0,1.0);opa=pow(opa,vGamma);fragColor=vColor*opa;if(uPickingEnabled){fragColor=vPickingColor;}}";
|
|
2
2
|
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "in mediump vec2 vertexCoord;in lowp vec2 textureCoord;in float width;out vec2 vTexCoord;out vec4 vColor;out float vSlope;
|
|
1
|
+
const shader = "in mediump vec2 vertexCoord;in lowp vec2 textureCoord;in float width;out vec2 vTexCoord;out float vEdgeFadeOpacity;flat out vec4 vColor;flat out float vSlope;flat out float vGamma;struct RangeResult{float pos;float scale;};float minValue(vec4 v){return min(min(v.x,v.y),min(v.z,v.w));}float maxValue(vec4 v){return max(max(v.x,v.y),max(v.z,v.w));}/***All measures are in[0,1]*/RangeResult positionInsideRange(float a,float b,float width,float padding,int align,bool flush){float span=b-a;float paddedWidth=width+2.0*padding;if(a>1.0||b<0.0){return RangeResult(0.0,0.0);}float extra=max(0.0,span-paddedWidth);float pos;if(align==0){float centre=a+b;if(flush){float leftOver=max(0.0,paddedWidth-centre);centre+=min(leftOver,extra);float rightOver=max(0.0,paddedWidth+centre-2.0);centre-=min(rightOver,extra);}pos=centre/2.0;}else if(align<0){float edge=a;if(flush){float over=max(0.0,-edge);edge+=min(over,extra);}pos=edge+padding;}else{float edge=b;if(flush){float over=max(0.0,edge-1.0);edge-=min(over,extra);}pos=edge-padding;}float scale=clamp((span-padding)/paddedWidth,0.0,1.0);return RangeResult(pos,scale);}vec2 calculateRotatedDimensions(float width,mat2 rotationMatrix){vec2 a=abs(rotationMatrix*vec2(width/2.0,0.5));vec2 b=abs(rotationMatrix*vec2(width/2.0,-0.5));return vec2(max(a.x,b.x),max(a.y,b.y))*2.0;}ivec2 fixAlignForAngle(ivec2 align,float angleInDegrees){float a=mod(angleInDegrees+45.0,360.0);int x=align.x;int y=-align.y;if(a<90.0){return ivec2(x,y);}else if(a<180.0){return ivec2(y,-x);}else if(a<270.0){return ivec2(-x,y);}else{return ivec2(-y,x);}}void main(void){float opacity=getScaled_opacity()*uViewOpacity;vec2 size=vec2(getScaled_size());float x=getScaled_x();float y=getScaled_y();float scale=1.0;float angleInDegrees=getScaled_angle();float angle=-angleInDegrees*PI/180.0;float sinTheta=sin(angle);float cosTheta=cos(angle);mat2 rotationMatrix=mat2(cosTheta,sinTheta,-sinTheta,cosTheta);vec2 flushSize=calculateRotatedDimensions(width,rotationMatrix);\n#if defined(x2_DEFINED) || defined(y2_DEFINED)\nivec2 align=fixAlignForAngle(uAlign,angleInDegrees);\n#else\nivec2 align=uAlign;\n#endif\n#ifdef x2_DEFINED\nfloat x2=getScaled_x2();if(uLogoLetter){size.x=(x2-x)*uViewportSize.x;x+=(x2-x)/2.0;}else{float x2=getScaled_x2();RangeResult result=positionInsideRange(min(x,x2),max(x,x2),size.x*scale*flushSize.x/uViewportSize.x,uPaddingX/uViewportSize.x,align.x,uFlushX);x=result.pos;scale*=result.scale;}\n#endif\nvec2 pos=applySampleFacet(vec2(x,y));\n#ifdef y2_DEFINED\nfloat y2=getScaled_y2();vec2 pos2=applySampleFacet(vec2(x,y2));if(uLogoLetter){size.y=(pos2.y-pos.y)*uViewportSize.y;pos.y+=(pos2.y-pos.y)/2.0;}else{RangeResult result=positionInsideRange(min(pos.y,pos2.y),max(pos.y,pos2.y),size.y*scale*flushSize.y/uViewportSize.y,uPaddingY/uViewportSize.y,align.y,uFlushY);pos.y=result.pos;scale*=result.scale;}\n#endif\nif(scale<1.0){if(uSqueeze){vec2 scaleFadeExtent=vec2(3.0,6.0)/size;if(scale<scaleFadeExtent[0]){gl_Position=vec4(0.0);return;}size*=scale;opacity*=linearstep(scaleFadeExtent[0],scaleFadeExtent[1],scale);}else if(scale<1.0){gl_Position=vec4(0.0);return;}}vec2 charPos=rotationMatrix*(vertexCoord*size+uD);vec2 unitPos=pos+charPos/uViewportSize;gl_Position=unitToNdc(unitPos);vSlope=max(1.0,min(size.x,size.y)/uSdfNumerator*uDevicePixelRatio);vec3 color=getScaled_color();vColor=vec4(color*opacity,opacity);vGamma=getGammaForColor(color);vTexCoord=textureCoord;if(maxValue(uViewportEdgeFadeDistance)>-pow(10.0,10.0)){vEdgeFadeOpacity=minValue(((vec4(1.0,1.0,0.0,0.0)+vec4(-1.0,-1.0,1.0,1.0)*unitPos.yxyx)*uViewportSize.yxyx-uViewportEdgeFadeDistance)/uViewportEdgeFadeWidth);}else{vEdgeFadeOpacity=1.0;}setupPicking();}";
|
|
2
2
|
export default shader;
|
|
@@ -77,6 +77,11 @@ export function isActiveIntervalSelection(selection: import("../types/selectionT
|
|
|
77
77
|
* @param {IntervalPoint} point
|
|
78
78
|
*/
|
|
79
79
|
export function selectionContainsPoint(selection: IntervalSelection, point: IntervalPoint): boolean;
|
|
80
|
+
/**
|
|
81
|
+
* @param {import("../spec/parameter.js").SelectionConfig["on"]} eventType
|
|
82
|
+
* @returns {import("../spec/parameter.js").EventConfig}
|
|
83
|
+
*/
|
|
84
|
+
export function asEventConfig(eventType: import("../spec/parameter.js").SelectionConfig["on"]): import("../spec/parameter.js").EventConfig;
|
|
80
85
|
export type IntervalSelection = import("../types/selectionTypes.js").IntervalSelection;
|
|
81
86
|
export type IntervalPoint = Partial<Record<keyof IntervalSelection["intervals"], number>>;
|
|
82
87
|
//# sourceMappingURL=selection.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/selection/selection.js"],"names":[],"mappings":"AAOA;;;GAGG;AACH,kDAHW,OAAO,qBAAqB,EAAE,KAAK,GACjC,OAAO,4BAA4B,EAAE,oBAAoB,CAQrE;AAED;;;GAGG;AACH,iDAHW,OAAO,qBAAqB,EAAE,KAAK,EAAE,GACnC,OAAO,4BAA4B,EAAE,mBAAmB,CAQpE;AAED;;;;GAIG;AACH,kDAHW,OAAO,oBAAoB,EAAE,gBAAgB,EAAE,GAC7C,OAAO,4BAA4B,EAAE,iBAAiB,CASlE;AAED;;;;;;;GAOG;AACH,qDAJW,OAAO,4BAA4B,EAAE,mBAAmB,2BACxD,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,QAAQ,GAAG,QAAQ,EAAE,QAAQ,CAAC,OAAO,qBAAqB,EAAE,KAAK,CAAC,CAAC,CAAC,GACzF,OAAO,4BAA4B,EAAE,mBAAmB,CA2BpE;AAED;;;;;GAKG;AACH,oDAHW,OAAO,sBAAsB,EAAE,qBAAqB,aACpD,OAAO,4BAA4B,EAAE,SAAS,UAgExD;AAED;;;GAGG;AACH,+CAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,iBAAiB,CAI/E;AAED;;;GAGG;AACH,kDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,oBAAoB,CAIlF;AAED;;;GAGG;AACH,iDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,mBAAmB,CAIjF;AAED;;;GAGG;AACH,gDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,kBAAkB,CAIhF;AAED;;;GAGG;AACH,gDAHW,OAAO,sBAAsB,EAAE,qBAAqB,GAClD,OAAO,sBAAsB,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../../src/selection/selection.js"],"names":[],"mappings":"AAOA;;;GAGG;AACH,kDAHW,OAAO,qBAAqB,EAAE,KAAK,GACjC,OAAO,4BAA4B,EAAE,oBAAoB,CAQrE;AAED;;;GAGG;AACH,iDAHW,OAAO,qBAAqB,EAAE,KAAK,EAAE,GACnC,OAAO,4BAA4B,EAAE,mBAAmB,CAQpE;AAED;;;;GAIG;AACH,kDAHW,OAAO,oBAAoB,EAAE,gBAAgB,EAAE,GAC7C,OAAO,4BAA4B,EAAE,iBAAiB,CASlE;AAED;;;;;;;GAOG;AACH,qDAJW,OAAO,4BAA4B,EAAE,mBAAmB,2BACxD,OAAO,CAAC,MAAM,CAAC,KAAK,GAAG,QAAQ,GAAG,QAAQ,EAAE,QAAQ,CAAC,OAAO,qBAAqB,EAAE,KAAK,CAAC,CAAC,CAAC,GACzF,OAAO,4BAA4B,EAAE,mBAAmB,CA2BpE;AAED;;;;;GAKG;AACH,oDAHW,OAAO,sBAAsB,EAAE,qBAAqB,aACpD,OAAO,4BAA4B,EAAE,SAAS,UAgExD;AAED;;;GAGG;AACH,+CAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,iBAAiB,CAI/E;AAED;;;GAGG;AACH,kDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,oBAAoB,CAIlF;AAED;;;GAGG;AACH,iDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,mBAAmB,CAIjF;AAED;;;GAGG;AACH,gDAHW,OAAO,4BAA4B,EAAE,SAAS,GAC5C,SAAS,IAAI,OAAO,4BAA4B,EAAE,kBAAkB,CAIhF;AAED;;;GAGG;AACH,gDAHW,OAAO,sBAAsB,EAAE,qBAAqB,GAClD,OAAO,sBAAsB,EAAE,eAAe,CA4B1D;AAED;;;GAGG;AACH,+CAHW,OAAO,sBAAsB,EAAE,eAAe,GAC5C,MAAM,IAAI,OAAO,sBAAsB,EAAE,oBAAoB,CAIzE;AAED;;;;GAIG;AACH,kDAHW,OAAO,sBAAsB,EAAE,eAAe,GAC5C,MAAM,IAAI,OAAO,sBAAsB,EAAE,uBAAuB,CAI5E;AAED;;GAEG;AACH,qDAFW,OAAO,4BAA4B,EAAE,iBAAiB,WAMhE;AAED;;;;;GAKG;AACH,kDAHW,iBAAiB,SACjB,aAAa,WAUvB;AAED;;;GAGG;AACH,yCAHW,OAAO,sBAAsB,EAAE,eAAe,CAAC,IAAI,CAAC,GAClD,OAAO,sBAAsB,EAAE,WAAW,CAsBtD;gCAvCY,OAAO,4BAA4B,EAAE,iBAAiB;4BACtD,OAAO,CAAC,MAAM,CAAC,MAAM,iBAAiB,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC"}
|
|
@@ -185,17 +185,28 @@ export function isProjectedSelection(selection) {
|
|
|
185
185
|
* @returns {import("../spec/parameter.js").SelectionConfig}
|
|
186
186
|
*/
|
|
187
187
|
export function asSelectionConfig(typeOrConfig) {
|
|
188
|
+
/** @type {import("../spec/parameter.js").SelectionConfig} */
|
|
188
189
|
const config =
|
|
189
190
|
typeof typeOrConfig === "string"
|
|
190
191
|
? { type: typeOrConfig }
|
|
191
|
-
: typeOrConfig;
|
|
192
|
+
: { ...typeOrConfig };
|
|
193
|
+
|
|
194
|
+
config.on = config.on
|
|
195
|
+
? asEventConfig(config.on)
|
|
196
|
+
: isPointSelectionConfig(config)
|
|
197
|
+
? { type: "click" }
|
|
198
|
+
: undefined;
|
|
199
|
+
|
|
200
|
+
config.clear =
|
|
201
|
+
config.clear === false
|
|
202
|
+
? undefined
|
|
203
|
+
: config.clear === true || config.clear == null
|
|
204
|
+
? { type: "dblclick" }
|
|
205
|
+
: asEventConfig(config.clear);
|
|
192
206
|
|
|
193
207
|
// Set some default
|
|
194
|
-
if (isPointSelectionConfig(config)) {
|
|
195
|
-
config.
|
|
196
|
-
if (config.on === "click") {
|
|
197
|
-
config.toggle = true;
|
|
198
|
-
}
|
|
208
|
+
if (isPointSelectionConfig(config) && config.on.type === "click") {
|
|
209
|
+
config.toggle = true;
|
|
199
210
|
}
|
|
200
211
|
|
|
201
212
|
return config;
|
|
@@ -242,3 +253,29 @@ export function selectionContainsPoint(selection, point) {
|
|
|
242
253
|
interval[1] >= point[channel]
|
|
243
254
|
);
|
|
244
255
|
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* @param {import("../spec/parameter.js").SelectionConfig["on"]} eventType
|
|
259
|
+
* @returns {import("../spec/parameter.js").EventConfig}
|
|
260
|
+
*/
|
|
261
|
+
export function asEventConfig(eventType) {
|
|
262
|
+
if (typeof eventType === "string") {
|
|
263
|
+
const m = eventType.match(/^([a-zA-Z]+)(?:\[(.+)\])?$/);
|
|
264
|
+
if (!m) {
|
|
265
|
+
throw new Error(`Invalid event type string: ${eventType}`);
|
|
266
|
+
}
|
|
267
|
+
const [, type, filter] = m;
|
|
268
|
+
/** @type {import("../spec/parameter.js").EventConfig} */
|
|
269
|
+
const eventSpec = {
|
|
270
|
+
type: /** @type {import("../spec/parameter.js").DomEventType} */ (
|
|
271
|
+
type
|
|
272
|
+
),
|
|
273
|
+
};
|
|
274
|
+
if (filter) {
|
|
275
|
+
eventSpec.filter = filter;
|
|
276
|
+
}
|
|
277
|
+
return eventSpec;
|
|
278
|
+
} else {
|
|
279
|
+
return eventType;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selection.test.d.ts","sourceRoot":"","sources":["../../../src/selection/selection.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { asEventConfig } from "./selection.js";
|
|
3
|
+
|
|
4
|
+
describe("asEventSpec", () => {
|
|
5
|
+
it("parses a simple string event type", () => {
|
|
6
|
+
const res = asEventConfig("click");
|
|
7
|
+
expect(res).toEqual({ type: "click" });
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("parses a string event type with bracket filter", () => {
|
|
11
|
+
const res = asEventConfig("click[event.shiftKey]");
|
|
12
|
+
expect(res).toEqual({ type: "click", filter: "event.shiftKey" });
|
|
13
|
+
});
|
|
14
|
+
});
|