@genome-spy/core 0.40.0 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundle/index.es.js +3615 -3460
- package/dist/bundle/index.js +69 -76
- package/dist/schema.json +196 -46
- package/dist/src/encoder/accessor.js +4 -2
- package/dist/src/genomeSpy.d.ts +2 -0
- package/dist/src/genomeSpy.d.ts.map +1 -1
- package/dist/src/genomeSpy.js +5 -0
- package/dist/src/gl/link.vertex.glsl.js +1 -1
- package/dist/src/gl/point.common.glsl.js +2 -0
- package/dist/src/gl/point.fragment.glsl.js +1 -1
- package/dist/src/gl/point.vertex.glsl.js +1 -1
- package/dist/src/gl/rect.vertex.glsl.js +1 -1
- package/dist/src/gl/rule.common.glsl.js +2 -0
- package/dist/src/gl/rule.fragment.glsl.js +1 -1
- package/dist/src/gl/rule.vertex.glsl.js +1 -1
- package/dist/src/gl/text.common.glsl.js +2 -0
- package/dist/src/gl/text.fragment.glsl.js +1 -1
- package/dist/src/gl/text.vertex.glsl.js +1 -1
- package/dist/src/marks/link.d.ts.map +1 -1
- package/dist/src/marks/link.js +28 -14
- package/dist/src/marks/mark.d.ts +34 -0
- package/dist/src/marks/mark.d.ts.map +1 -1
- package/dist/src/marks/mark.js +83 -1
- package/dist/src/marks/pointMark.d.ts.map +1 -1
- package/dist/src/marks/pointMark.js +21 -9
- package/dist/src/marks/rectMark.d.ts +1 -2
- package/dist/src/marks/rectMark.d.ts.map +1 -1
- package/dist/src/marks/rectMark.js +28 -17
- package/dist/src/marks/rule.d.ts.map +1 -1
- package/dist/src/marks/rule.js +17 -6
- package/dist/src/marks/text.d.ts.map +1 -1
- package/dist/src/marks/text.js +22 -7
- package/dist/src/paramBroker.d.ts +30 -0
- package/dist/src/paramBroker.d.ts.map +1 -0
- package/dist/src/paramBroker.js +102 -0
- package/dist/src/spec/mark.d.ts +27 -18
- package/dist/src/spec/view.d.ts +2 -1
- package/dist/src/types/viewContext.d.ts +2 -0
- package/dist/src/utils/expression.d.ts +12 -2
- package/dist/src/utils/expression.d.ts.map +1 -1
- package/dist/src/utils/expression.js +68 -9
- package/dist/src/utils/linearstep.d.ts +7 -0
- package/dist/src/utils/linearstep.d.ts.map +1 -0
- package/dist/src/utils/linearstep.js +10 -0
- package/dist/src/view/view.d.ts.map +1 -1
- package/dist/src/view/view.js +6 -0
- package/package.json +2 -2
package/dist/schema.json
CHANGED
|
@@ -1108,6 +1108,19 @@
|
|
|
1108
1108
|
],
|
|
1109
1109
|
"type": "object"
|
|
1110
1110
|
},
|
|
1111
|
+
"ExprRef": {
|
|
1112
|
+
"additionalProperties": false,
|
|
1113
|
+
"properties": {
|
|
1114
|
+
"expr": {
|
|
1115
|
+
"description": "The expression string.",
|
|
1116
|
+
"type": "string"
|
|
1117
|
+
}
|
|
1118
|
+
},
|
|
1119
|
+
"required": [
|
|
1120
|
+
"expr"
|
|
1121
|
+
],
|
|
1122
|
+
"type": "object"
|
|
1123
|
+
},
|
|
1111
1124
|
"Field": {
|
|
1112
1125
|
"description": "The name of the field or a JavaScript expression for accessing nested properties. Dots and brackets in the field name must be escaped.",
|
|
1113
1126
|
"type": "string"
|
|
@@ -2470,13 +2483,23 @@
|
|
|
2470
2483
|
{
|
|
2471
2484
|
"const": false,
|
|
2472
2485
|
"type": "boolean"
|
|
2486
|
+
},
|
|
2487
|
+
{
|
|
2488
|
+
"$ref": "#/definitions/ExprRef"
|
|
2473
2489
|
}
|
|
2474
2490
|
],
|
|
2475
2491
|
"description": "The range of the `\"arc\"` shape's fading distance in pixels. This property allows for making the arc's opacity fade out as it extends away from the chord. The fading distance is interpolated from one to zero between the interval defined by this property. Both `false` and `[0, 0]` disable fading.\n\n**Default value:** `false`"
|
|
2476
2492
|
},
|
|
2477
2493
|
"arcHeightFactor": {
|
|
2478
|
-
"
|
|
2479
|
-
|
|
2494
|
+
"anyOf": [
|
|
2495
|
+
{
|
|
2496
|
+
"type": "number"
|
|
2497
|
+
},
|
|
2498
|
+
{
|
|
2499
|
+
"$ref": "#/definitions/ExprRef"
|
|
2500
|
+
}
|
|
2501
|
+
],
|
|
2502
|
+
"description": "Scaling factor for the `\"arc`\" shape's height. The default value `1.0` produces roughly circular arcs.\n\n**Default value:** `1.0`"
|
|
2480
2503
|
},
|
|
2481
2504
|
"baseline": {
|
|
2482
2505
|
"$ref": "#/definitions/Baseline",
|
|
@@ -2487,8 +2510,15 @@
|
|
|
2487
2510
|
"type": "boolean"
|
|
2488
2511
|
},
|
|
2489
2512
|
"clampApex": {
|
|
2490
|
-
"
|
|
2491
|
-
|
|
2513
|
+
"anyOf": [
|
|
2514
|
+
{
|
|
2515
|
+
"type": "boolean"
|
|
2516
|
+
},
|
|
2517
|
+
{
|
|
2518
|
+
"$ref": "#/definitions/ExprRef"
|
|
2519
|
+
}
|
|
2520
|
+
],
|
|
2521
|
+
"description": "Whether the apex of the `\"dome\"` shape is clamped to the viewport edge. When over a half of the dome is located outside the viewport, clamping allows for more accurate reading of the value encoded by the apex' position.\n\n**Default value:** `false`"
|
|
2492
2522
|
},
|
|
2493
2523
|
"clip": {
|
|
2494
2524
|
"anyOf": [
|
|
@@ -2506,24 +2536,59 @@
|
|
|
2506
2536
|
"type": "string"
|
|
2507
2537
|
},
|
|
2508
2538
|
"cornerRadius": {
|
|
2509
|
-
"
|
|
2510
|
-
|
|
2539
|
+
"anyOf": [
|
|
2540
|
+
{
|
|
2541
|
+
"type": "number"
|
|
2542
|
+
},
|
|
2543
|
+
{
|
|
2544
|
+
"$ref": "#/definitions/ExprRef"
|
|
2545
|
+
}
|
|
2546
|
+
],
|
|
2547
|
+
"description": "Radius of the rounded corners.\n\n**Default value:** `0`"
|
|
2511
2548
|
},
|
|
2512
2549
|
"cornerRadiusBottomLeft": {
|
|
2513
|
-
"
|
|
2514
|
-
|
|
2550
|
+
"anyOf": [
|
|
2551
|
+
{
|
|
2552
|
+
"type": "number"
|
|
2553
|
+
},
|
|
2554
|
+
{
|
|
2555
|
+
"$ref": "#/definitions/ExprRef"
|
|
2556
|
+
}
|
|
2557
|
+
],
|
|
2558
|
+
"description": "Radius of the bottom left rounded corner. Has higher precedence than `cornerRadius`.\n\n**Default value:** (None)"
|
|
2515
2559
|
},
|
|
2516
2560
|
"cornerRadiusBottomRight": {
|
|
2517
|
-
"
|
|
2518
|
-
|
|
2561
|
+
"anyOf": [
|
|
2562
|
+
{
|
|
2563
|
+
"type": "number"
|
|
2564
|
+
},
|
|
2565
|
+
{
|
|
2566
|
+
"$ref": "#/definitions/ExprRef"
|
|
2567
|
+
}
|
|
2568
|
+
],
|
|
2569
|
+
"description": "Radius of the bottom right rounded corner. Has higher precedence than `cornerRadius`.\n\n**Default value:** (None)"
|
|
2519
2570
|
},
|
|
2520
2571
|
"cornerRadiusTopLeft": {
|
|
2521
|
-
"
|
|
2522
|
-
|
|
2572
|
+
"anyOf": [
|
|
2573
|
+
{
|
|
2574
|
+
"type": "number"
|
|
2575
|
+
},
|
|
2576
|
+
{
|
|
2577
|
+
"$ref": "#/definitions/ExprRef"
|
|
2578
|
+
}
|
|
2579
|
+
],
|
|
2580
|
+
"description": "Radius of the top left rounded corner. Has higher precedence than `cornerRadius`.\n\n**Default value:** (None)"
|
|
2523
2581
|
},
|
|
2524
2582
|
"cornerRadiusTopRight": {
|
|
2525
|
-
"
|
|
2526
|
-
|
|
2583
|
+
"anyOf": [
|
|
2584
|
+
{
|
|
2585
|
+
"type": "number"
|
|
2586
|
+
},
|
|
2587
|
+
{
|
|
2588
|
+
"$ref": "#/definitions/ExprRef"
|
|
2589
|
+
}
|
|
2590
|
+
],
|
|
2591
|
+
"description": "Radius of the top right rounded corner. Has higher precedence than `cornerRadius`.\n\n**Default value:** (None)"
|
|
2527
2592
|
},
|
|
2528
2593
|
"dx": {
|
|
2529
2594
|
"description": "The horizontal offset between the text and its anchor point, in pixels. Applied after the rotation by `angle`.",
|
|
@@ -2582,61 +2647,132 @@
|
|
|
2582
2647
|
"type": "boolean"
|
|
2583
2648
|
},
|
|
2584
2649
|
"linkShape": {
|
|
2585
|
-
"
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2650
|
+
"anyOf": [
|
|
2651
|
+
{
|
|
2652
|
+
"const": "arc",
|
|
2653
|
+
"type": "string"
|
|
2654
|
+
},
|
|
2655
|
+
{
|
|
2656
|
+
"const": "diagonal",
|
|
2657
|
+
"type": "string"
|
|
2658
|
+
},
|
|
2659
|
+
{
|
|
2660
|
+
"const": "line",
|
|
2661
|
+
"type": "string"
|
|
2662
|
+
},
|
|
2663
|
+
{
|
|
2664
|
+
"const": "dome",
|
|
2665
|
+
"type": "string"
|
|
2666
|
+
},
|
|
2667
|
+
{
|
|
2668
|
+
"$ref": "#/definitions/ExprRef"
|
|
2669
|
+
}
|
|
2591
2670
|
],
|
|
2592
|
-
"
|
|
2671
|
+
"description": "The shape of the link path. Either `\"arc\"`, `\"diagonal\"`, `\"line\"`, or `\"dome\"`.\n\n**Default value:** `\"arc\"`"
|
|
2593
2672
|
},
|
|
2594
2673
|
"logoLetters": {
|
|
2595
2674
|
"description": "Stretch letters so that they can be used with [sequence logos](https://en.wikipedia.org/wiki/Sequence_logo), etc...",
|
|
2596
2675
|
"type": "boolean"
|
|
2597
2676
|
},
|
|
2598
2677
|
"maxChordLength": {
|
|
2599
|
-
"
|
|
2600
|
-
|
|
2678
|
+
"anyOf": [
|
|
2679
|
+
{
|
|
2680
|
+
"type": "number"
|
|
2681
|
+
},
|
|
2682
|
+
{
|
|
2683
|
+
"$ref": "#/definitions/ExprRef"
|
|
2684
|
+
}
|
|
2685
|
+
],
|
|
2686
|
+
"description": "The maximum length of `\"arc\"` shape's chord in pixels. The chord is the line segment between the two points that define the arc. Limiting the chord length serves two purposes when zooming in close enough: 1) it prevents the arc from becoming a straight line and 2) it mitigates the limited precision of floating point numbers in arc rendering.\n\n**Default value:** `50000`"
|
|
2601
2687
|
},
|
|
2602
2688
|
"minArcHeight": {
|
|
2603
|
-
"
|
|
2604
|
-
|
|
2689
|
+
"anyOf": [
|
|
2690
|
+
{
|
|
2691
|
+
"type": "number"
|
|
2692
|
+
},
|
|
2693
|
+
{
|
|
2694
|
+
"$ref": "#/definitions/ExprRef"
|
|
2695
|
+
}
|
|
2696
|
+
],
|
|
2697
|
+
"description": "The minimum height of an `\"arc\"` shape. Makes very short links more clearly visible.\n\n**Default value:** `1.5`"
|
|
2605
2698
|
},
|
|
2606
2699
|
"minBufferSize": {
|
|
2607
2700
|
"description": "Minimum size for WebGL buffers (number of data items). Allows for using `bufferSubData()` to update graphics.\n\nThis property is intended for internal use.",
|
|
2608
2701
|
"type": "number"
|
|
2609
2702
|
},
|
|
2610
2703
|
"minHeight": {
|
|
2611
|
-
"
|
|
2612
|
-
|
|
2704
|
+
"anyOf": [
|
|
2705
|
+
{
|
|
2706
|
+
"type": "number"
|
|
2707
|
+
},
|
|
2708
|
+
{
|
|
2709
|
+
"$ref": "#/definitions/ExprRef"
|
|
2710
|
+
}
|
|
2711
|
+
],
|
|
2712
|
+
"description": "The minimum height of a rectangle in pixels. The property clamps rectangles' heights.\n\n**Default value:** `0`"
|
|
2613
2713
|
},
|
|
2614
2714
|
"minLength": {
|
|
2615
|
-
"
|
|
2616
|
-
|
|
2715
|
+
"anyOf": [
|
|
2716
|
+
{
|
|
2717
|
+
"type": "number"
|
|
2718
|
+
},
|
|
2719
|
+
{
|
|
2720
|
+
"$ref": "#/definitions/ExprRef"
|
|
2721
|
+
}
|
|
2722
|
+
],
|
|
2723
|
+
"description": "The minimum length of the rule in pixels. Use this property to ensure that very short ranged rules remain visible even when the user zooms out.\n\n**Default value:** `0`"
|
|
2617
2724
|
},
|
|
2618
2725
|
"minOpacity": {
|
|
2619
|
-
"
|
|
2620
|
-
|
|
2726
|
+
"anyOf": [
|
|
2727
|
+
{
|
|
2728
|
+
"type": "number"
|
|
2729
|
+
},
|
|
2730
|
+
{
|
|
2731
|
+
"$ref": "#/definitions/ExprRef"
|
|
2732
|
+
}
|
|
2733
|
+
],
|
|
2734
|
+
"description": "Clamps the minimum size-dependent opacity. The property does not affect the `opacity` channel. Valid values are between `0` and `1`.\n\nWhen a rectangle would be smaller than what is specified in `minHeight` and `minWidth`, it is faded out proportionally. Example: a rectangle would be rendered as one pixel wide, but `minWidth` clamps it to five pixels. The rectangle is actually rendered as five pixels wide, but its opacity is multiplied by 0.2. With this setting, you can limit the factor to, for example, 0.5 to keep the rectangles more clearly visible.\n\n**Default value:** `0`"
|
|
2621
2735
|
},
|
|
2622
2736
|
"minPickingSize": {
|
|
2623
|
-
"
|
|
2624
|
-
|
|
2737
|
+
"anyOf": [
|
|
2738
|
+
{
|
|
2739
|
+
"type": "number"
|
|
2740
|
+
},
|
|
2741
|
+
{
|
|
2742
|
+
"$ref": "#/definitions/ExprRef"
|
|
2743
|
+
}
|
|
2744
|
+
],
|
|
2745
|
+
"description": "The minimum stroke width of the links when pointing with the mouse cursor. Allows making very thin links easier to point at.\n\n**Default value:** `3.0`"
|
|
2625
2746
|
},
|
|
2626
2747
|
"minWidth": {
|
|
2627
|
-
"
|
|
2628
|
-
|
|
2748
|
+
"anyOf": [
|
|
2749
|
+
{
|
|
2750
|
+
"type": "number"
|
|
2751
|
+
},
|
|
2752
|
+
{
|
|
2753
|
+
"$ref": "#/definitions/ExprRef"
|
|
2754
|
+
}
|
|
2755
|
+
],
|
|
2756
|
+
"description": "The minimum width of a rectangle in pixels. The property clamps rectangles' widths when the viewport is zoomed out.\n\nThis property also reduces flickering of very narrow rectangles when zooming. The value should generally be at least one.\n\n**Default value:** `1`"
|
|
2629
2757
|
},
|
|
2630
2758
|
"opacity": {
|
|
2631
2759
|
"type": "number"
|
|
2632
2760
|
},
|
|
2633
2761
|
"orient": {
|
|
2634
|
-
"
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2762
|
+
"anyOf": [
|
|
2763
|
+
{
|
|
2764
|
+
"const": "vertical",
|
|
2765
|
+
"type": "string"
|
|
2766
|
+
},
|
|
2767
|
+
{
|
|
2768
|
+
"const": "horizontal",
|
|
2769
|
+
"type": "string"
|
|
2770
|
+
},
|
|
2771
|
+
{
|
|
2772
|
+
"$ref": "#/definitions/ExprRef"
|
|
2773
|
+
}
|
|
2638
2774
|
],
|
|
2639
|
-
"
|
|
2775
|
+
"description": "The orientation of the link path. Either `\"vertical\"` or `\"horizontal\"`. Only applies to diagonal links.\n\n**Default value:** `\"vertical\"`"
|
|
2640
2776
|
},
|
|
2641
2777
|
"paddingX": {
|
|
2642
2778
|
"description": "The horizontal padding, in pixels, when the `x2` channel is used for ranged text.\n\n**Default value:** `0`",
|
|
@@ -2675,13 +2811,24 @@
|
|
|
2675
2811
|
"type": "string"
|
|
2676
2812
|
},
|
|
2677
2813
|
"strokeCap": {
|
|
2678
|
-
"
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2814
|
+
"anyOf": [
|
|
2815
|
+
{
|
|
2816
|
+
"const": "butt",
|
|
2817
|
+
"type": "string"
|
|
2818
|
+
},
|
|
2819
|
+
{
|
|
2820
|
+
"const": "square",
|
|
2821
|
+
"type": "string"
|
|
2822
|
+
},
|
|
2823
|
+
{
|
|
2824
|
+
"const": "round",
|
|
2825
|
+
"type": "string"
|
|
2826
|
+
},
|
|
2827
|
+
{
|
|
2828
|
+
"$ref": "#/definitions/ExprRef"
|
|
2829
|
+
}
|
|
2683
2830
|
],
|
|
2684
|
-
"
|
|
2831
|
+
"description": "The style of stroke ends. Available choices: `\"butt\"`, `\"round`\", and `\"square\"`.\n\n**Default value:** `\"butt\"`"
|
|
2685
2832
|
},
|
|
2686
2833
|
"strokeDash": {
|
|
2687
2834
|
"description": "An array of of alternating stroke and gap lengths or `null` for solid strokes.\n\n**Default value:** `null`",
|
|
@@ -6310,6 +6457,9 @@
|
|
|
6310
6457
|
},
|
|
6311
6458
|
{
|
|
6312
6459
|
"$ref": "#/definitions/DynamicOpacity"
|
|
6460
|
+
},
|
|
6461
|
+
{
|
|
6462
|
+
"$ref": "#/definitions/ExprRef"
|
|
6313
6463
|
}
|
|
6314
6464
|
]
|
|
6315
6465
|
},
|
|
@@ -70,7 +70,9 @@ export default class AccessorFactory {
|
|
|
70
70
|
* @param {string} expr
|
|
71
71
|
*/
|
|
72
72
|
function createExpressionAccessor(expr) {
|
|
73
|
-
const
|
|
74
|
-
accessor
|
|
73
|
+
const fn = createFunction(expr);
|
|
74
|
+
const accessor = /** @type {Accessor} */ (/** @type {any} */ (fn));
|
|
75
|
+
// Not bulletproof and probably erroneous with global params
|
|
76
|
+
accessor.constant = accessor.fields.length == 0;
|
|
75
77
|
return accessor;
|
|
76
78
|
}
|
package/dist/src/genomeSpy.d.ts
CHANGED
|
@@ -67,6 +67,7 @@ export default class GenomeSpy {
|
|
|
67
67
|
tooltipHandlers: Record<string, import("./tooltip/tooltipHandler.js").TooltipHandler>;
|
|
68
68
|
/** @type {View} */
|
|
69
69
|
viewRoot: import("./view/view.js").default;
|
|
70
|
+
_paramBroker: ParamBroker;
|
|
70
71
|
/**
|
|
71
72
|
*
|
|
72
73
|
* @param {(name: string) => any[]} provider
|
|
@@ -135,6 +136,7 @@ import Animator from "./utils/animator.js";
|
|
|
135
136
|
import GenomeStore from "./genome/genomeStore.js";
|
|
136
137
|
import BufferedViewRenderingContext from "./view/renderingContext/bufferedViewRenderingContext.js";
|
|
137
138
|
import Inertia from "./utils/inertia.js";
|
|
139
|
+
import ParamBroker from "./paramBroker.js";
|
|
138
140
|
import WebGLHelper from "./gl/webGLHelper.js";
|
|
139
141
|
import Tooltip from "./utils/ui/tooltip.js";
|
|
140
142
|
import UnitView from "./view/unitView.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":"AA0CA;IACI;;;;;OAKG;IAEH;;;;;OAKG;IACH,uBAJW,WAAW,qDAEX,OAAO,qBAAqB,EAAE,YAAY,EA+EpD;IA5EG,uBAA0B;IAM1B,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,0BAAqC;IAGzC;;;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,0BA2BC;IAvBG,uBAOC;IAED,sCAA0D;IAK1D,iBAA0C;IAW9C;;OAEG;IACH,gBAiBC;IAED,sCAyMC;IAED;;;OAGG;IACH,UAFa,QAAQ,OAAO,CAAC,CAqC5B;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,sBAyCC;IAED,kBAIC;IAED,iCAOC;IAED,iCASC;IAED,qFAWC;CACJ;;;;iCArvBY,eAAe,GAAG,YAAY,GAAG,QAAQ,GAAG,gBAAgB;4BAhC7C,uBAAuB;4BA0BP,uBAAuB;qBAZ9C,qBAAqB;wBAIlB,yBAAyB;yCARR,yDAAyD;oBAYvD,oBAAoB;wBAMvC,kBAAkB;wBApBlB,qBAAqB;oBAVzB,uBAAuB;qBAQtB,oBAAoB"}
|
package/dist/src/genomeSpy.js
CHANGED
|
@@ -31,6 +31,7 @@ import dataTooltipHandler from "./tooltip/dataTooltipHandler.js";
|
|
|
31
31
|
import { invalidatePrefix } from "./utils/propertyCacher.js";
|
|
32
32
|
import { VIEW_ROOT_NAME, ViewFactory } from "./view/viewFactory.js";
|
|
33
33
|
import { reconfigureScales } from "./view/scaleResolution.js";
|
|
34
|
+
import ParamBroker from "./paramBroker.js";
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Events that are broadcasted to all views.
|
|
@@ -128,6 +129,8 @@ export default class GenomeSpy {
|
|
|
128
129
|
|
|
129
130
|
/** @type {View} */
|
|
130
131
|
this.viewRoot = undefined;
|
|
132
|
+
|
|
133
|
+
this._paramBroker = new ParamBroker();
|
|
131
134
|
}
|
|
132
135
|
|
|
133
136
|
/**
|
|
@@ -255,6 +258,8 @@ export default class GenomeSpy {
|
|
|
255
258
|
return self._glHelper.dpr;
|
|
256
259
|
},
|
|
257
260
|
|
|
261
|
+
paramBroker: this._paramBroker,
|
|
262
|
+
|
|
258
263
|
requestLayoutReflow: () => {
|
|
259
264
|
// placeholder
|
|
260
265
|
},
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "uniform float uArcHeightFactor;uniform float uMinArcHeight;uniform float uMinPickingSize;uniform int uShape;uniform int uOrient;uniform bool uClampApex;uniform float uMaxChordLength;uniform vec2 uArcFadingDistance;in vec2 strip;out vec4 vColor;out float vSize;out float vNormalLengthInPixels;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;}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){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);vSize=paddedSize;setupPicking();}";
|
|
1
|
+
const shader = "uniform Mark{uniform float uArcHeightFactor;uniform float uMinArcHeight;uniform float uMinPickingSize;uniform int uShape;uniform int uOrient;uniform bool uClampApex;uniform float uMaxChordLength;uniform vec2 uArcFadingDistance;};in vec2 strip;out vec4 vColor;out float vSize;out float vNormalLengthInPixels;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;}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){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);vSize=paddedSize;setupPicking();}";
|
|
2
2
|
export default shader;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const shader = "uniform Mark{/***The stroke should only grow inwards,e.g,the diameter/outline is not affected by the stroke width.*Thus,a point that has a zero size has no visible stroke. This allows strokes to be used with*geometric zoom,etc.*/uniform bool uInwardStroke;uniform lowp float uMaxRelativePointDiameter;uniform mediump float uScaleFactor;uniform mediump float uMaxPointSize;uniform mediump float uZoomLevel;uniform highp float uSemanticThreshold;uniform mediump float uGradientStrength;};";
|
|
2
|
+
export default shader;
|
|
@@ -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);
|
|
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,vHalfStrokeWidth);}else if(d-vHalfStrokeWidth<=0.0){fragColor=vPickingColor;}else{discard;}}";
|
|
2
2
|
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "
|
|
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;}/***Computes a scaling factor for the points in a sample-faceted view.*/float getDownscaleFactor(vec2 pos){if(!isFacetedSamples()){return 1.0;}float sampleFacetHeight=getSampleFacetHeight(pos);float maxPointDiameter=sqrt(uMaxPointSize);float factor=sampleFacetHeight*uViewportSize.y*uMaxRelativePointDiameter;return clamp(0.0,maxPointDiameter,factor)/maxPointDiameter;}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=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*getDownscaleFactor(pos);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=(diameter+padding)*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 = "
|
|
1
|
+
const shader = "uniform Mark{uniform float uMinWidth;uniform float uMinHeight;uniform float uMinOpacity;uniform float uCornerRadiusTopRight;uniform float uCornerRadiusBottomRight;uniform float uCornerRadiusTopLeft;uniform float uCornerRadiusBottomLeft;};/***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.*/in vec2 frac;out lowp vec4 vFillColor;out lowp vec4 vStrokeColor;out float vHalfStrokeWidth;out vec4 vCornerRadii;\n#if defined(ROUNDED_CORNERS) || defined(STROKED)\nout vec2 vPosInPixels;\n#endif\nout vec2 vHalfSizeInPixels;/***Clamps the minimumSize and returns an opacity that reflects the amount of clamping.*/float clampMinSize(inout float pos,float frac,float size,float minSize){if(minSize>0.0&&abs(size)<minSize){pos+=(frac-0.5)*(minSize*sign(size)-size);return abs(size)/minSize;}return 1.0;}void sort(inout float a,inout float b){if(a>b){float tmp=b;b=a;a=tmp;}}void main(void){vec2 normalizedMinSize=vec2(uMinWidth,uMinHeight)/uViewportSize;vec4 cornerRadii=vec4(uCornerRadiusTopRight,uCornerRadiusBottomRight,uCornerRadiusBottomLeft,uCornerRadiusTopLeft);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));pos=applySampleFacet(pos);\n#if defined(ROUNDED_CORNERS) || defined(STROKED)\nfloat aaPadding=1.0/uDevicePixelRatio;float strokeWidth=getScaled_strokeWidth();float strokeOpacity=getScaled_strokeOpacity()*opaFactor;vec2 centeredFrac=frac-0.5;vec2 expand=centeredFrac*(strokeWidth+aaPadding)/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;
|
|
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;}}";
|
|
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;
|
|
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();}";
|
|
2
2
|
export default shader;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const shader = "uniform Mark{uniform mediump float uSdfNumerator;uniform mediump vec2 uD;uniform mediump vec4 uViewportEdgeFadeWidth;uniform mediump vec4 uViewportEdgeFadeDistance;uniform bool uSqueeze;uniform bool uLogoLetter;uniform lowp ivec2 uAlign;uniform mediump float uPaddingX;uniform bool uFlushX;uniform mediump float uPaddingY;uniform bool uFlushY;};";
|
|
2
|
+
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "uniform sampler2D uTexture;
|
|
1
|
+
const shader = "uniform sampler2D uTexture;in vec2 vTexCoord;in float vEdgeFadeOpacity;in vec4 vColor;in float vSlope;out lowp vec4 fragColor;float median(float r,float g,float b){return max(min(r,g),min(max(r,g),b));}void main(){vec3 c=texture(uTexture,vTexCoord).rgb;float sigDist=1.0-median(c.r,c.g,c.b);float slope=uLogoLetter? 0.7/length(vec2(dFdy(sigDist),dFdx(sigDist))): vSlope;float opa=clamp((sigDist-0.5)*slope+0.5,0.0,1.0);opa*=pow(clamp(vEdgeFadeOpacity,0.0,1.0),2.2);fragColor=vColor*opa;if(uPickingEnabled){fragColor=vPickingColor;}}";
|
|
2
2
|
export default shader;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const shader = "
|
|
1
|
+
const shader = "in mediump vec2 vertexCoord;in lowp vec2 textureCoord;in float width;out vec2 vTexCoord;out vec4 vColor;out float vSlope;out float vEdgeFadeOpacity;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);vColor=vec4(getScaled_color()*opacity,opacity);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;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/marks/link.js"],"names":[],"mappings":"AAWA;
|
|
1
|
+
{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/marks/link.js"],"names":[],"mappings":"AAWA;IA+HQ;;;;;;MAKC;CA2DR;iBArMgB,WAAW"}
|
package/dist/src/marks/link.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { drawBufferInfo, setBuffersAndAttributes
|
|
1
|
+
import { drawBufferInfo, setBuffersAndAttributes } from "twgl.js";
|
|
2
2
|
import VERTEX_SHADER from "../gl/link.vertex.glsl.js";
|
|
3
3
|
import FRAGMENT_SHADER from "../gl/link.fragment.glsl.js";
|
|
4
4
|
import { LinkVertexBuilder } from "../gl/dataToVertices.js";
|
|
@@ -97,17 +97,22 @@ export default class LinkMark extends Mark {
|
|
|
97
97
|
|
|
98
98
|
const props = this.properties;
|
|
99
99
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
100
|
+
this.registerMarkUniform(
|
|
101
|
+
"uArcFadingDistance",
|
|
102
|
+
props.arcFadingDistance,
|
|
103
|
+
(x) => x || /** @type {[number, number]} */ ([0, 0])
|
|
104
|
+
);
|
|
105
|
+
this.registerMarkUniform("uArcHeightFactor", props.arcHeightFactor);
|
|
106
|
+
this.registerMarkUniform("uMinArcHeight", props.minArcHeight);
|
|
107
|
+
this.registerMarkUniform("uMinPickingSize", props.minPickingSize);
|
|
108
|
+
this.registerMarkUniform("uShape", props.linkShape, (linkShape) =>
|
|
109
|
+
LINK_SHAPES.indexOf(linkShape)
|
|
110
|
+
);
|
|
111
|
+
this.registerMarkUniform("uOrient", props.orient, (orient) =>
|
|
112
|
+
ORIENTS.indexOf(orient)
|
|
113
|
+
);
|
|
114
|
+
this.registerMarkUniform("uClampApex", props.clampApex, (x) => !!x);
|
|
115
|
+
this.registerMarkUniform("uMaxChordLength", props.maxChordLength);
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
updateGraphicsData() {
|
|
@@ -141,14 +146,23 @@ export default class LinkMark extends Mark {
|
|
|
141
146
|
this.updateBufferInfo(vertexData);
|
|
142
147
|
}
|
|
143
148
|
|
|
149
|
+
/**
|
|
150
|
+
* @param {import("../types/rendering.js").GlobalRenderingOptions} options
|
|
151
|
+
*/
|
|
152
|
+
prepareRender(options) {
|
|
153
|
+
const ops = super.prepareRender(options);
|
|
154
|
+
|
|
155
|
+
ops.push(() => this.bindOrSetMarkUniformBlock());
|
|
156
|
+
|
|
157
|
+
return ops;
|
|
158
|
+
}
|
|
159
|
+
|
|
144
160
|
/**
|
|
145
161
|
* @param {import("./mark.js").MarkRenderingOptions} options
|
|
146
162
|
*/
|
|
147
163
|
render(options) {
|
|
148
164
|
const gl = this.gl;
|
|
149
165
|
|
|
150
|
-
// TODO: Vertical clipping in faceted view
|
|
151
|
-
|
|
152
166
|
return this.createRenderCallback((offset, count) => {
|
|
153
167
|
// We are using instanced drawing here.
|
|
154
168
|
// However, WebGL does not provide glDrawArraysInstancedBaseInstance and thus,
|