@fjader/svelte 0.2.3 → 0.2.5
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/README.md +3 -1
- package/dist/animation/EntranceGate.d.ts +52 -0
- package/dist/animation/EntranceGate.js +93 -0
- package/dist/animation/TransitionClock.d.ts +61 -30
- package/dist/animation/TransitionClock.js +67 -29
- package/dist/animation/transition-log.d.ts +41 -0
- package/dist/animation/transition-log.js +57 -0
- package/dist/components/axes/AxisBottom.svelte +27 -8
- package/dist/components/axes/AxisBottom.svelte.d.ts +10 -0
- package/dist/components/axes/AxisCenter.svelte +4 -2
- package/dist/components/axes/AxisLeft.svelte +81 -10
- package/dist/components/axes/AxisLeft.svelte.d.ts +17 -0
- package/dist/components/axes/BandAxisTicks.svelte +4 -3
- package/dist/components/axes/axis-title.d.ts +30 -0
- package/dist/components/axes/axis-title.js +77 -0
- package/dist/components/charts/ChartCell.svelte +33 -6
- package/dist/components/charts/ChartCell.svelte.d.ts +9 -0
- package/dist/components/charts/ChartContainer.svelte +55 -5
- package/dist/components/charts/ChartContainer.svelte.d.ts +14 -1
- package/dist/components/charts/ChartHover.svelte.d.ts +14 -0
- package/dist/components/charts/ChartHover.svelte.js +22 -0
- package/dist/components/charts/ChartVisibility.svelte.d.ts +43 -0
- package/dist/components/charts/ChartVisibility.svelte.js +67 -0
- package/dist/components/guides/Grid.svelte +12 -1
- package/dist/components/guides/legend/ContinuousColorLegend.svelte +7 -1
- package/dist/components/guides/legend/OrdinalColorLegend.svelte +8 -5
- package/dist/components/marks/AreaMarkX.svelte +18 -4
- package/dist/components/marks/AreaMarkY.svelte +18 -4
- package/dist/components/marks/BarMarkX.svelte +20 -4
- package/dist/components/marks/BarMarkY.svelte +20 -4
- package/dist/components/marks/DotsMark.svelte +8 -3
- package/dist/components/marks/LineMark.svelte +13 -6
- package/dist/components/marks/ParallelCoordinatesMark.svelte +11 -2
- package/dist/components/marks/ParallelCoordinatesMark.svelte.d.ts +4 -0
- package/dist/components/marks/RectMark.svelte +8 -3
- package/dist/components/marks/RectXMark.svelte +9 -3
- package/dist/components/marks/RectYMark.svelte +9 -3
- package/dist/components/marks/RuleMarkX.svelte +31 -25
- package/dist/components/marks/RuleMarkY.svelte +31 -25
- package/dist/components/marks/TextMark.svelte +52 -14
- package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.d.ts +22 -1
- package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.js +579 -66
- package/dist/components/marks/lifecycle/domain-queries.d.ts +13 -2
- package/dist/components/marks/lifecycle/domain-queries.js +43 -11
- package/dist/components/marks/lifecycle/domain-registration.d.ts +6 -1
- package/dist/components/marks/lifecycle/domain-registration.js +17 -20
- package/dist/components/marks/lifecycle/other-rows.svelte.d.ts +112 -0
- package/dist/components/marks/lifecycle/other-rows.svelte.js +193 -0
- package/dist/components/marks/lifecycle/other-split.d.ts +80 -0
- package/dist/components/marks/lifecycle/other-split.js +112 -0
- package/dist/components/marks/lifecycle/query-builder.d.ts +53 -3
- package/dist/components/marks/lifecycle/query-builder.js +46 -23
- package/dist/components/marks/utils/MarkColor.svelte.d.ts +3 -1
- package/dist/components/marks/utils/MarkColor.svelte.js +33 -3
- package/dist/components/marks/utils/MarkSeries.svelte.d.ts +14 -1
- package/dist/components/marks/utils/MarkSeries.svelte.js +25 -1
- package/dist/components/marks/utils/MarkSize.svelte.js +4 -0
- package/dist/components/marks/utils/reactive-config.d.ts +1 -1
- package/dist/components/marks/utils/reactive-config.js +9 -0
- package/dist/components/marks/utils/tooltip-helpers.d.ts +4 -1
- package/dist/components/marks/utils/tooltip-helpers.js +2 -1
- package/dist/components/rendering/Areas.svelte +57 -19
- package/dist/components/rendering/Areas.svelte.d.ts +12 -0
- package/dist/components/rendering/BaseGPURenderer.svelte.d.ts +3 -1
- package/dist/components/rendering/BaseGPURenderer.svelte.js +4 -2
- package/dist/components/rendering/Dots.svelte +23 -3
- package/dist/components/rendering/Dots.svelte.d.ts +6 -0
- package/dist/components/rendering/GridLine.svelte +13 -1
- package/dist/components/rendering/GridLine.svelte.d.ts +5 -0
- package/dist/components/rendering/Lines.svelte +48 -13
- package/dist/components/rendering/Lines.svelte.d.ts +12 -0
- package/dist/components/rendering/ParallelLines.svelte +5 -5
- package/dist/components/rendering/Rects.svelte +164 -30
- package/dist/components/rendering/Rects.svelte.d.ts +23 -2
- package/dist/components/rendering/RuleX.svelte +1 -1
- package/dist/components/rendering/RuleY.svelte +1 -1
- package/dist/components/rendering/WebGPUCanvas.svelte +4 -2
- package/dist/components/rendering/activity-reads.d.ts +47 -12
- package/dist/components/rendering/activity-reads.js +61 -19
- package/dist/components/rendering/uniform-sizes.d.ts +1 -1
- package/dist/components/rendering/uniform-sizes.js +1 -1
- package/dist/config/ChartConfig.svelte.d.ts +10 -1
- package/dist/config/ChartConfig.svelte.js +17 -0
- package/dist/gpu/GPUCoordinator.svelte.d.ts +31 -1
- package/dist/gpu/GPUCoordinator.svelte.js +164 -7
- package/dist/gpu/MorphedChannels.d.ts +11 -28
- package/dist/gpu/MorphedChannels.js +72 -8
- package/dist/gpu/ScaleTemplateSystem.d.ts +20 -2
- package/dist/gpu/ScaleTemplateSystem.js +83 -6
- package/dist/index.d.ts +19 -4
- package/dist/index.js +22 -4
- package/dist/interactors/Interval1D.svelte +6 -1
- package/dist/interactors/Interval2D.svelte +6 -1
- package/dist/interactors/ParallelAxisSource.svelte +10 -1
- package/dist/interactors/Toggle.svelte +32 -3
- package/dist/interactors/Tooltip.svelte +138 -41
- package/dist/interactors/TooltipManager.svelte.d.ts +20 -5
- package/dist/interactors/TooltipManager.svelte.js +46 -12
- package/dist/interactors/other-tooltip.d.ts +16 -0
- package/dist/interactors/other-tooltip.js +22 -0
- package/dist/query-engine/CrossfilterSelection.svelte.d.ts +4 -2
- package/dist/query-engine/CrossfilterSelection.svelte.js +2 -0
- package/dist/query-engine/FieldActivity.svelte.d.ts +49 -1
- package/dist/query-engine/FieldActivity.svelte.js +175 -5
- package/dist/query-engine/FilterGroup.svelte.d.ts +23 -1
- package/dist/query-engine/FilterGroup.svelte.js +43 -3
- package/dist/query-engine/FilterGroupRegistry.svelte.d.ts +31 -3
- package/dist/query-engine/FilterGroupRegistry.svelte.js +62 -15
- package/dist/query-engine/MarkHandle.svelte.d.ts +28 -1
- package/dist/query-engine/MarkHandle.svelte.js +33 -1
- package/dist/query-engine/QueryEngine.d.ts +225 -5
- package/dist/query-engine/QueryEngine.js +697 -47
- package/dist/query-engine/categorical-identity.d.ts +41 -0
- package/dist/query-engine/categorical-identity.js +145 -65
- package/dist/query-engine/debug/query-log.d.ts +39 -0
- package/dist/query-engine/debug/query-log.js +90 -0
- package/dist/query-engine/duckdb.d.ts +55 -8
- package/dist/query-engine/duckdb.js +82 -30
- package/dist/query-engine/index.d.ts +7 -4
- package/dist/query-engine/index.js +3 -3
- package/dist/query-engine/preagg/BuildQueue.d.ts +33 -13
- package/dist/query-engine/preagg/BuildQueue.js +51 -15
- package/dist/query-engine/preagg/Preagg.d.ts +46 -3
- package/dist/query-engine/preagg/Preagg.js +159 -31
- package/dist/query-engine/preagg/plan.d.ts +33 -1
- package/dist/query-engine/preagg/plan.js +158 -14
- package/dist/query-engine/sliced-lane.d.ts +108 -0
- package/dist/query-engine/sliced-lane.js +299 -0
- package/dist/query-engine/source-routing.d.ts +106 -0
- package/dist/query-engine/source-routing.js +189 -0
- package/dist/query-engine/toggle-predicate.d.ts +21 -0
- package/dist/query-engine/toggle-predicate.js +29 -1
- package/dist/scales/ActivityTable.d.ts +5 -1
- package/dist/scales/ActivityTable.js +12 -3
- package/dist/scales/BandScaleState.svelte.d.ts +22 -9
- package/dist/scales/BandScaleState.svelte.js +39 -21
- package/dist/scales/ChartScales.svelte.d.ts +3 -0
- package/dist/scales/ChartScales.svelte.js +26 -8
- package/dist/scales/ColorScaleState.svelte.d.ts +18 -2
- package/dist/scales/ColorScaleState.svelte.js +138 -26
- package/dist/scales/LinearScaleState.svelte.d.ts +7 -10
- package/dist/scales/LinearScaleState.svelte.js +21 -39
- package/dist/scales/ScaleGeneration.svelte.d.ts +48 -0
- package/dist/scales/ScaleGeneration.svelte.js +42 -0
- package/dist/scales/ScaleRegistry.svelte.js +3 -1
- package/dist/scales/SlotTransition.d.ts +15 -1
- package/dist/scales/SlotTransition.js +33 -4
- package/dist/scales/TimeScaleState.svelte.d.ts +7 -3
- package/dist/scales/TimeScaleState.svelte.js +7 -7
- package/dist/scales/color-utils.d.ts +0 -3
- package/dist/scales/color-utils.js +0 -3
- package/dist/scales/entered.d.ts +8 -0
- package/dist/scales/entered.js +10 -0
- package/dist/spec/LazyQueryEngine.js +2 -19
- package/dist/spec/MarkRegistry.d.ts +3 -1
- package/dist/spec/MarkRegistry.js +13 -1
- package/dist/spec/PlotFromSpec.svelte +1 -0
- package/dist/spec/export.js +11 -2
- package/dist/spec/types.d.ts +43 -13
- package/dist/sql/bin.d.ts +25 -0
- package/dist/sql/bin.js +108 -5
- package/dist/theme.css +5 -4
- package/dist/transforms/TransformCompiler.d.ts +47 -2
- package/dist/transforms/TransformCompiler.js +70 -1
- package/dist/transforms/index.js +176 -42
- package/dist/types.d.ts +177 -2
- package/package.json +4 -3
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
import { getGPUContext } from '../../gpu';
|
|
6
6
|
import { DEFAULT_FILL_COLOR } from '../../scales/color-utils';
|
|
7
7
|
import type { ChartContext, WebGPUCanvasContext } from '../../types';
|
|
8
|
-
import {
|
|
8
|
+
import type { SplitProp } from '../marks/lifecycle/other-rows.svelte';
|
|
9
|
+
import { activityReads, markActivityWGSL, otherRowActivityWGSL } from './activity-reads';
|
|
9
10
|
|
|
10
11
|
const rectRendererDefinition = {
|
|
11
12
|
x: { concept: 'extent', channels: ['x0', 'x1'] },
|
|
@@ -21,7 +22,18 @@
|
|
|
21
22
|
Y1: 3,
|
|
22
23
|
COLOR: 4,
|
|
23
24
|
ALPHA: 5,
|
|
24
|
-
CONSTANTS: 6
|
|
25
|
+
CONSTANTS: 6,
|
|
26
|
+
/**
|
|
27
|
+
* An Other bar's selected share, per row: 0 on rows that are not an Other
|
|
28
|
+
* (so the zero-filled stand-in buffer means "no split anywhere"), `1 +
|
|
29
|
+
* share` on one. Morphed with the bar's length.
|
|
30
|
+
*
|
|
31
|
+
* The vertex stage's 8th storage buffer: six channels, the identity slot
|
|
32
|
+
* table and this fill WebGPU's default maxStorageBuffersPerShaderStage. A
|
|
33
|
+
* further per-row channel needs another container (an instance vertex
|
|
34
|
+
* attribute) or a raised device limit.
|
|
35
|
+
*/
|
|
36
|
+
SHARE: 7
|
|
25
37
|
};
|
|
26
38
|
|
|
27
39
|
// Facet uses vertex buffer slot 1 (not a storage binding)
|
|
@@ -35,8 +47,10 @@
|
|
|
35
47
|
GROUP_INDEX: 12,
|
|
36
48
|
CONSTANT_COLOR: 16,
|
|
37
49
|
DX: 32,
|
|
38
|
-
DY: 36
|
|
39
|
-
|
|
50
|
+
DY: 36,
|
|
51
|
+
OTHER_COLOR_ON_BAND: 40,
|
|
52
|
+
SPLIT_ALONG_X: 44,
|
|
53
|
+
ENTRANCE_AXIS: 48
|
|
40
54
|
};
|
|
41
55
|
|
|
42
56
|
interface Props {
|
|
@@ -46,8 +60,20 @@
|
|
|
46
60
|
y1Data: Float32Array;
|
|
47
61
|
colorValueData: Float32Array | null;
|
|
48
62
|
alphaData: Float32Array | null;
|
|
63
|
+
/**
|
|
64
|
+
* A bar's selected share per row (see BINDINGS.SHARE), or null for none: a
|
|
65
|
+
* bar mark with a topN Other bucket passes its lifecycle's `otherRows.split`.
|
|
66
|
+
* The fragment draws the bar above the share dimmed.
|
|
67
|
+
*/
|
|
68
|
+
share?: SplitProp | null;
|
|
49
69
|
facetData?: Float32Array | null;
|
|
50
70
|
dataVersion: number;
|
|
71
|
+
/**
|
|
72
|
+
* The data version whose first write lands without morphing, or 0: a
|
|
73
|
+
* catch-up result (MarkLifecycleV2.landsFor). Later writes of that version
|
|
74
|
+
* animate as usual.
|
|
75
|
+
*/
|
|
76
|
+
landsFor?: number;
|
|
51
77
|
zIndex?: number;
|
|
52
78
|
colorMode?: number;
|
|
53
79
|
colorScaleIndex?: number;
|
|
@@ -60,14 +86,22 @@
|
|
|
60
86
|
markId?: string;
|
|
61
87
|
/**
|
|
62
88
|
* The band axis, when this mark's rows are one per category in category
|
|
63
|
-
* order and may therefore morph
|
|
89
|
+
* order and may therefore morph; or a histogram's binned axis, one row per
|
|
90
|
+
* bin in bin order. null to morph nothing.
|
|
64
91
|
*
|
|
65
92
|
* The OTHER axis's channels morph. The band's never do: they carry a
|
|
66
93
|
* category id that the shader resolves through the slot table, and
|
|
67
94
|
* interpolating an identity produces a fraction that resolves to some
|
|
68
|
-
* other category. Position already animates, through the slot table.
|
|
95
|
+
* other category. Position already animates, through the slot table. A
|
|
96
|
+
* bin's edges do not change under a filter, and a re-bin snaps.
|
|
69
97
|
*/
|
|
70
98
|
bandAxis?: 'x' | 'y' | null;
|
|
99
|
+
/**
|
|
100
|
+
* The axis this mark grows along when its chart enters: its measure axis,
|
|
101
|
+
* for bars and histograms anchored at 0. null fades it in instead, for
|
|
102
|
+
* rects with bounds of their own (a Gantt bar has no 0 to grow from).
|
|
103
|
+
*/
|
|
104
|
+
grow?: 'x' | 'y' | null;
|
|
71
105
|
}
|
|
72
106
|
|
|
73
107
|
let {
|
|
@@ -77,8 +111,10 @@
|
|
|
77
111
|
y1Data,
|
|
78
112
|
colorValueData,
|
|
79
113
|
alphaData,
|
|
114
|
+
share = null,
|
|
80
115
|
facetData = null,
|
|
81
116
|
dataVersion,
|
|
117
|
+
landsFor = 0,
|
|
82
118
|
zIndex = 0,
|
|
83
119
|
colorMode = 0,
|
|
84
120
|
colorScaleIndex = 0,
|
|
@@ -88,9 +124,15 @@
|
|
|
88
124
|
dx = 0,
|
|
89
125
|
dy = 0,
|
|
90
126
|
markId = '',
|
|
91
|
-
bandAxis = null
|
|
127
|
+
bandAxis = null,
|
|
128
|
+
grow = null
|
|
92
129
|
}: Props = $props();
|
|
93
130
|
|
|
131
|
+
const splitData = $derived(share?.data ?? null);
|
|
132
|
+
const splitSlides = $derived(share?.slides ?? true);
|
|
133
|
+
// Bars grouped on y run along x, so their split does too.
|
|
134
|
+
const splitAlongX = $derived(share?.axis === 'y');
|
|
135
|
+
const otherColorOnBand = $derived(share?.colorOnBand ?? false);
|
|
94
136
|
const morphX = $derived(bandAxis === 'y');
|
|
95
137
|
const morphY = $derived(bandAxis === 'x');
|
|
96
138
|
|
|
@@ -137,8 +179,12 @@
|
|
|
137
179
|
constantColor: vec4<f32>, // Used when colorMode = 0
|
|
138
180
|
dx: f32, // Horizontal pixel offset
|
|
139
181
|
dy: f32, // Vertical pixel offset
|
|
140
|
-
|
|
141
|
-
|
|
182
|
+
otherColorOnBand: u32, // 1: an Other row skips its colour activity too
|
|
183
|
+
splitAlongX: u32, // 1: an Other bar splits along x (horizontal bars)
|
|
184
|
+
entranceAxis: u32, // 0: fades in, 1: grows along x, 2: along y
|
|
185
|
+
_pad0: u32,
|
|
186
|
+
_pad1: u32,
|
|
187
|
+
_pad2: u32,
|
|
142
188
|
};
|
|
143
189
|
@group(1) @binding(6) var<uniform> markConstants: MarkConstants;
|
|
144
190
|
|
|
@@ -146,6 +192,13 @@
|
|
|
146
192
|
@builtin(position) position: vec4<f32>,
|
|
147
193
|
@location(0) colorValue: f32, // Raw value for scale lookup
|
|
148
194
|
@location(1) alpha: f32,
|
|
195
|
+
// The Other bar's selected share, or -1 on every other row; and where this
|
|
196
|
+
// fragment sits along the bar, 0 at its base, 1 at its end.
|
|
197
|
+
@location(2) @interpolate(flat) share: f32,
|
|
198
|
+
@location(3) along: f32,
|
|
199
|
+
// An Other bar's unselected part: dimmed by the other fields' activity and
|
|
200
|
+
// by the field's free slot, so it fades as the rest of the chart does.
|
|
201
|
+
@location(4) alphaRest: f32,
|
|
149
202
|
};
|
|
150
203
|
|
|
151
204
|
@group(1) @binding(0) var<storage, read> x0Values: array<f32>;
|
|
@@ -154,6 +207,7 @@
|
|
|
154
207
|
@group(1) @binding(3) var<storage, read> y1Values: array<f32>;
|
|
155
208
|
@group(1) @binding(4) var<storage, read> colorValues: array<f32>;
|
|
156
209
|
@group(1) @binding(5) var<storage, read> alphaValues: array<f32>;
|
|
210
|
+
@group(1) @binding(7) var<storage, read> splitValues: array<f32>;
|
|
157
211
|
|
|
158
212
|
@vertex
|
|
159
213
|
fn vertexMain(
|
|
@@ -175,13 +229,19 @@
|
|
|
175
229
|
// Y axis scaling (generated based on scale type)
|
|
176
230
|
{{Y_AXIS_LOGIC}}
|
|
177
231
|
|
|
232
|
+
// The chart's entrance: both edges pulled toward 0 on the measure axis,
|
|
233
|
+
// so a stack grows as one block rather than its segments floating up.
|
|
234
|
+
let p0 = entrancePosition(vec2<f32>(scaledX0, scaledY0), markConstants.entranceAxis);
|
|
235
|
+
let p1 = entrancePosition(vec2<f32>(scaledX1, scaledY1), markConstants.entranceAxis);
|
|
236
|
+
|
|
178
237
|
// Apply inset (shrink rect inward on all sides)
|
|
179
|
-
let ix = markConstants.inset * sign(
|
|
180
|
-
let iy = markConstants.inset * sign(
|
|
238
|
+
let ix = markConstants.inset * sign(p1.x - p0.x);
|
|
239
|
+
let iy = markConstants.inset * sign(p1.y - p0.y);
|
|
181
240
|
|
|
182
241
|
// Interpolate rectangle corners and apply pixel offsets
|
|
183
|
-
let finalX = mix(
|
|
184
|
-
let finalY = mix(
|
|
242
|
+
let finalX = mix(p0.x + ix, p1.x - ix, rectCorner.x) + markConstants.dx;
|
|
243
|
+
let finalY = mix(p0.y + iy, p1.y - iy, rectCorner.y) + markConstants.dy;
|
|
244
|
+
let enterAlpha = entranceAlpha(markConstants.entranceAxis);
|
|
185
245
|
|
|
186
246
|
// Convert to normalized device coordinates
|
|
187
247
|
let worldPos = vec2<f32>(finalX, finalY);
|
|
@@ -190,19 +250,47 @@
|
|
|
190
250
|
var output: VertexOutput;
|
|
191
251
|
output.position = vec4<f32>(normalizedPos.x, -normalizedPos.y, 0.0, 1.0);
|
|
192
252
|
output.colorValue = colorValue;
|
|
193
|
-
|
|
194
|
-
|
|
253
|
+
// An Other row (split > 0) is drawn in two parts, mixed in the fragment at
|
|
254
|
+
// its share. Below: as any bar, by its full activity, its own field's
|
|
255
|
+
// included, so it dims and lights with the bucket's lit state (#23). Above:
|
|
256
|
+
// by the other fields' activity and the field's free slot, so it is lit
|
|
257
|
+
// only while nothing is selected. Both fade on the selection clock, and the
|
|
258
|
+
// split only moves when the share moves between two parts that differ.
|
|
259
|
+
let split = splitValues[instanceIdx];
|
|
260
|
+
let isOther = split > 0.5;
|
|
261
|
+
output.share = select(-1.0, split - 1.0, isOther);
|
|
262
|
+
output.along = select(rectCorner.y, rectCorner.x, markConstants.splitAlongX == 1u);
|
|
263
|
+
let activity = ${markActivityWGSL(ACTIVITY_READS, {
|
|
264
|
+
color: 'markConstants.colorMode, markConstants.colorScaleIndex, colorValue',
|
|
265
|
+
x: 'x0',
|
|
266
|
+
y: 'y0',
|
|
267
|
+
group: 'markConstants.groupIndex'
|
|
268
|
+
})};
|
|
269
|
+
output.alpha = alpha * selectionDim(activity) * enterAlpha;
|
|
270
|
+
// The unselected part is drawn only on an Other row: every other bar skips
|
|
271
|
+
// its activity reads.
|
|
272
|
+
output.alphaRest = output.alpha;
|
|
273
|
+
if (isOther) {
|
|
274
|
+
let otherActivity = ${otherRowActivityWGSL(ACTIVITY_READS, {
|
|
195
275
|
color: 'markConstants.colorMode, markConstants.colorScaleIndex, colorValue',
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
276
|
+
group: 'markConstants.groupIndex',
|
|
277
|
+
skipColor: 'markConstants.otherColorOnBand == 1u'
|
|
278
|
+
})};
|
|
279
|
+
let free = select(
|
|
280
|
+
bandFreeActivityX(markConstants.groupIndex),
|
|
281
|
+
bandFreeActivityY(markConstants.groupIndex),
|
|
282
|
+
markConstants.splitAlongX == 1u
|
|
283
|
+
);
|
|
284
|
+
output.alphaRest = alpha * selectionDim(min(otherActivity, free)) * enterAlpha;
|
|
285
|
+
}
|
|
201
286
|
return output;
|
|
202
287
|
}
|
|
203
288
|
|
|
204
289
|
@fragment
|
|
205
290
|
fn fragmentMain(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
291
|
+
// Before any branch: a derivative must be taken in uniform control flow.
|
|
292
|
+
let aa = max(fwidth(input.along), 1e-4);
|
|
293
|
+
|
|
206
294
|
// Get color based on mode
|
|
207
295
|
var baseColor: vec4<f32>;
|
|
208
296
|
if (markConstants.colorMode == 0u) {
|
|
@@ -217,7 +305,14 @@
|
|
|
217
305
|
);
|
|
218
306
|
}
|
|
219
307
|
|
|
220
|
-
|
|
308
|
+
var finalAlpha = baseColor.a * input.alpha;
|
|
309
|
+
// An Other bar's split: its own part up to the selected share, from its
|
|
310
|
+
// base, its unselected part above, with an anti-aliased edge. At share 1
|
|
311
|
+
// the whole bar is its own part, with no half-dimmed top row.
|
|
312
|
+
if (input.share >= 0.0 && input.share < 1.0) {
|
|
313
|
+
let below = 1.0 - smoothstep(input.share - aa, input.share + aa, input.along);
|
|
314
|
+
finalAlpha = baseColor.a * mix(input.alphaRest, input.alpha, below);
|
|
315
|
+
}
|
|
221
316
|
return vec4<f32>(baseColor.rgb * finalAlpha, finalAlpha);
|
|
222
317
|
}
|
|
223
318
|
`
|
|
@@ -248,6 +343,7 @@
|
|
|
248
343
|
{ binding: BINDINGS.Y1, type: 'read-only-storage', visibility: GPUShaderStage.VERTEX },
|
|
249
344
|
{ binding: BINDINGS.COLOR, type: 'read-only-storage', visibility: GPUShaderStage.VERTEX },
|
|
250
345
|
{ binding: BINDINGS.ALPHA, type: 'read-only-storage', visibility: GPUShaderStage.VERTEX },
|
|
346
|
+
{ binding: BINDINGS.SHARE, type: 'read-only-storage', visibility: GPUShaderStage.VERTEX },
|
|
251
347
|
{
|
|
252
348
|
binding: BINDINGS.CONSTANTS,
|
|
253
349
|
type: 'uniform',
|
|
@@ -257,6 +353,18 @@
|
|
|
257
353
|
|
|
258
354
|
// --- DATA WRITING EFFECTS (Independent & Fine-Grained) ---
|
|
259
355
|
|
|
356
|
+
// Whether this write lands: the first of the catch-up's data version
|
|
357
|
+
// (landsFor). Plain, not $state: only the write effect reads and sets it.
|
|
358
|
+
// Assumes a catch-up result is ONE morph write: should it ever take two
|
|
359
|
+
// (values, then band ids after the instant layout), the second springs.
|
|
360
|
+
// A morph SPRING right after a morph snap on a return points here.
|
|
361
|
+
let lastMorphedVersion = -1;
|
|
362
|
+
function landsNow(): boolean {
|
|
363
|
+
const first = dataVersion !== lastMorphedVersion;
|
|
364
|
+
lastMorphedVersion = dataVersion;
|
|
365
|
+
return first && landsFor !== 0 && landsFor === dataVersion;
|
|
366
|
+
}
|
|
367
|
+
|
|
260
368
|
// The measure axis's two edges morph, as ONE write per data update, so one
|
|
261
369
|
// update starts one transition. The band's ids go with them: they are how a
|
|
262
370
|
// row set that is not the one being animated gets noticed and snapped.
|
|
@@ -266,16 +374,40 @@
|
|
|
266
374
|
// a fraction that the slot table resolves to a DIFFERENT category.
|
|
267
375
|
$effect(() => {
|
|
268
376
|
if (!renderer?.resourcesCreated || !bandAxis) return;
|
|
377
|
+
// The Other share travels with the bar's length, on the same clock, so the
|
|
378
|
+
// split and the bar land together. A share that changes alone (a click)
|
|
379
|
+
// starts a transition of its own on that clock.
|
|
380
|
+
const split = splitData ? ([[BINDINGS.SHARE, splitData]] as const) : [];
|
|
381
|
+
const land = landsNow() ? 'all' : splitData && !splitSlides ? [BINDINGS.SHARE] : undefined;
|
|
269
382
|
if (bandAxis === 'x') {
|
|
270
|
-
renderer.writeMorphed(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
383
|
+
renderer.writeMorphed(
|
|
384
|
+
'x',
|
|
385
|
+
x0Data,
|
|
386
|
+
[[BINDINGS.Y0, y0Data], [BINDINGS.Y1, y1Data], ...split],
|
|
387
|
+
land
|
|
388
|
+
);
|
|
274
389
|
} else {
|
|
275
|
-
renderer.writeMorphed(
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
390
|
+
renderer.writeMorphed(
|
|
391
|
+
'y',
|
|
392
|
+
y0Data,
|
|
393
|
+
[[BINDINGS.X0, x0Data], [BINDINGS.X1, x1Data], ...split],
|
|
394
|
+
land
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
});
|
|
398
|
+
// Without a band axis the share is written as is. A mark that had shares and
|
|
399
|
+
// has none now writes one array of zeros, which also drops a morphed channel:
|
|
400
|
+
// left alone, the shader would keep reading the last shares. A mark that
|
|
401
|
+
// never had any writes nothing and reads the zero-filled stand-in.
|
|
402
|
+
let splitWritten = false;
|
|
403
|
+
$effect(() => {
|
|
404
|
+
if (!renderer?.resourcesCreated) return;
|
|
405
|
+
if (splitData) {
|
|
406
|
+
if (!bandAxis) renderer.writeAttribute(BINDINGS.SHARE, splitData);
|
|
407
|
+
splitWritten = true;
|
|
408
|
+
} else if (splitWritten) {
|
|
409
|
+
renderer.writeAttribute(BINDINGS.SHARE, new Float32Array(Math.max(1, x0Data.length)));
|
|
410
|
+
splitWritten = false;
|
|
279
411
|
}
|
|
280
412
|
});
|
|
281
413
|
$effect(() => {
|
|
@@ -324,7 +456,9 @@
|
|
|
324
456
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 12, constantColor[3], LE);
|
|
325
457
|
view.setFloat32(UNIFORM_OFFSETS.DX, dx, LE);
|
|
326
458
|
view.setFloat32(UNIFORM_OFFSETS.DY, dy, LE);
|
|
327
|
-
|
|
459
|
+
view.setUint32(UNIFORM_OFFSETS.OTHER_COLOR_ON_BAND, otherColorOnBand ? 1 : 0, LE);
|
|
460
|
+
view.setUint32(UNIFORM_OFFSETS.SPLIT_ALONG_X, splitAlongX ? 1 : 0, LE);
|
|
461
|
+
view.setUint32(UNIFORM_OFFSETS.ENTRANCE_AXIS, grow === 'x' ? 1 : grow === 'y' ? 2 : 0, LE);
|
|
328
462
|
|
|
329
463
|
renderer.writeUniform(BINDINGS.CONSTANTS, new Uint8Array(buffer));
|
|
330
464
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SplitProp } from '../marks/lifecycle/other-rows.svelte';
|
|
1
2
|
interface Props {
|
|
2
3
|
x0Data: Float32Array;
|
|
3
4
|
x1Data: Float32Array;
|
|
@@ -5,8 +6,20 @@ interface Props {
|
|
|
5
6
|
y1Data: Float32Array;
|
|
6
7
|
colorValueData: Float32Array | null;
|
|
7
8
|
alphaData: Float32Array | null;
|
|
9
|
+
/**
|
|
10
|
+
* A bar's selected share per row (see BINDINGS.SHARE), or null for none: a
|
|
11
|
+
* bar mark with a topN Other bucket passes its lifecycle's `otherRows.split`.
|
|
12
|
+
* The fragment draws the bar above the share dimmed.
|
|
13
|
+
*/
|
|
14
|
+
share?: SplitProp | null;
|
|
8
15
|
facetData?: Float32Array | null;
|
|
9
16
|
dataVersion: number;
|
|
17
|
+
/**
|
|
18
|
+
* The data version whose first write lands without morphing, or 0: a
|
|
19
|
+
* catch-up result (MarkLifecycleV2.landsFor). Later writes of that version
|
|
20
|
+
* animate as usual.
|
|
21
|
+
*/
|
|
22
|
+
landsFor?: number;
|
|
10
23
|
zIndex?: number;
|
|
11
24
|
colorMode?: number;
|
|
12
25
|
colorScaleIndex?: number;
|
|
@@ -19,14 +32,22 @@ interface Props {
|
|
|
19
32
|
markId?: string;
|
|
20
33
|
/**
|
|
21
34
|
* The band axis, when this mark's rows are one per category in category
|
|
22
|
-
* order and may therefore morph
|
|
35
|
+
* order and may therefore morph; or a histogram's binned axis, one row per
|
|
36
|
+
* bin in bin order. null to morph nothing.
|
|
23
37
|
*
|
|
24
38
|
* The OTHER axis's channels morph. The band's never do: they carry a
|
|
25
39
|
* category id that the shader resolves through the slot table, and
|
|
26
40
|
* interpolating an identity produces a fraction that resolves to some
|
|
27
|
-
* other category. Position already animates, through the slot table.
|
|
41
|
+
* other category. Position already animates, through the slot table. A
|
|
42
|
+
* bin's edges do not change under a filter, and a re-bin snaps.
|
|
28
43
|
*/
|
|
29
44
|
bandAxis?: 'x' | 'y' | null;
|
|
45
|
+
/**
|
|
46
|
+
* The axis this mark grows along when its chart enters: its measure axis,
|
|
47
|
+
* for bars and histograms anchored at 0. null fades it in instead, for
|
|
48
|
+
* rects with bounds of their own (a Gantt bar has no 0 to grow from).
|
|
49
|
+
*/
|
|
50
|
+
grow?: 'x' | 'y' | null;
|
|
30
51
|
}
|
|
31
52
|
declare const Rects: import("svelte").Component<Props, {}, "">;
|
|
32
53
|
type Rects = ReturnType<typeof Rects>;
|
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
var output: VertexOutput;
|
|
182
182
|
output.position = vec4<f32>(normalizedPos.x, -normalizedPos.y, 0.0, 1.0);
|
|
183
183
|
output.colorValue = colorValue;
|
|
184
|
-
output.alpha = alpha * selectionDim(
|
|
184
|
+
output.alpha = alpha * entranceAlpha(0u) * selectionDim(
|
|
185
185
|
${markActivityWGSL(ACTIVITY_READS, {
|
|
186
186
|
color: 'markConstants.colorMode, markConstants.colorScaleIndex, colorValue',
|
|
187
187
|
x: 'x',
|
|
@@ -180,7 +180,7 @@
|
|
|
180
180
|
var output: VertexOutput;
|
|
181
181
|
output.position = vec4<f32>(normalizedPos.x, -normalizedPos.y, 0.0, 1.0);
|
|
182
182
|
output.colorValue = colorValue;
|
|
183
|
-
output.alpha = alpha * selectionDim(
|
|
183
|
+
output.alpha = alpha * entranceAlpha(0u) * selectionDim(
|
|
184
184
|
${markActivityWGSL(ACTIVITY_READS, {
|
|
185
185
|
color: 'markConstants.colorMode, markConstants.colorScaleIndex, colorValue',
|
|
186
186
|
x: 'x0',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { onMount, onDestroy, setContext, getContext } from 'svelte';
|
|
3
3
|
import { getGPUContext } from '../../gpu';
|
|
4
4
|
import type { Snippet } from 'svelte';
|
|
5
|
-
import type { ChartContext, WebGPUCanvasContext } from '../../types';
|
|
5
|
+
import type { ChartContext, EntranceMode, WebGPUCanvasContext } from '../../types';
|
|
6
6
|
import type { GPUCoordinator, ChartRegistrationResult } from '../../gpu/GPUCoordinator.svelte';
|
|
7
7
|
import type { FacetScaleRef } from '../../gpu/GPUCoordinator.svelte';
|
|
8
8
|
|
|
@@ -120,7 +120,9 @@
|
|
|
120
120
|
chartControl = gpuCoordinator.registerChart(chartId, canvas, {
|
|
121
121
|
zIndex: 0,
|
|
122
122
|
facetIndex: facetIndex ?? 0,
|
|
123
|
-
facetScale
|
|
123
|
+
facetScale,
|
|
124
|
+
entrance: c.config?.chartProps?.entrance as EntranceMode | undefined,
|
|
125
|
+
entranceGate: c.config?.entrance ?? null
|
|
124
126
|
});
|
|
125
127
|
|
|
126
128
|
// Notify coordinator that context is ready
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Which selection activities a mark reads: its ordinal colour, its band x,
|
|
3
|
-
* its band y. One answer per renderer, used
|
|
3
|
+
* its band y, and a line's or area's series. One answer per renderer, used
|
|
4
|
+
* twice:
|
|
4
5
|
*
|
|
5
6
|
* - The renderer builds its shader's `markActivity` call from it, so a read
|
|
6
7
|
* the table does not list is passed as 1.0 and cannot happen.
|
|
@@ -26,11 +27,14 @@ export interface ActivityReads {
|
|
|
26
27
|
readonly color: boolean;
|
|
27
28
|
readonly x: boolean;
|
|
28
29
|
readonly y: boolean;
|
|
30
|
+
/** A line's or area's `z`: the series field when it is not the colour field. */
|
|
31
|
+
readonly series: boolean;
|
|
29
32
|
}
|
|
30
33
|
/**
|
|
31
34
|
* What a renderer reads. `hasExtent` is a rule's: RuleX with y1/y2, RuleY with
|
|
32
|
-
* x1/x2. Lines
|
|
33
|
-
* a band axis spans its categories.
|
|
35
|
+
* x1/x2. Lines and areas dim by colour and by series (`z`), never by a band
|
|
36
|
+
* axis: a line over a band axis spans its categories. Parallel coordinates
|
|
37
|
+
* have no `z` and dim by colour only.
|
|
34
38
|
*/
|
|
35
39
|
export declare function activityReads(renderer: ActivityRenderer, hasExtent?: boolean): ActivityReads;
|
|
36
40
|
/**
|
|
@@ -47,12 +51,14 @@ export declare function rendererForMark(markType: string): ActivityRenderer | nu
|
|
|
47
51
|
* sorted, from what its renderer reads and the identity key of each of its
|
|
48
52
|
* categorical scales (null for a channel with no such scale, or a scale with
|
|
49
53
|
* no identity: a field with no identity has no activity to dim by, so a
|
|
50
|
-
* selection on it filters the mark).
|
|
54
|
+
* selection on it filters the mark). `series` is null unless the mark has a
|
|
55
|
+
* `z` of its own; a series that is the colour field is already in `color`.
|
|
51
56
|
*/
|
|
52
57
|
export declare function readsFor(reads: ActivityReads, keys: {
|
|
53
58
|
color: string | null;
|
|
54
59
|
x: string | null;
|
|
55
60
|
y: string | null;
|
|
61
|
+
series?: string | null;
|
|
56
62
|
}): readonly string[];
|
|
57
63
|
/** A mark that reads no activity. Shared, so its reads never look changed. */
|
|
58
64
|
export declare const NO_READS: readonly string[];
|
|
@@ -62,22 +68,51 @@ export declare const NO_READS: readonly string[];
|
|
|
62
68
|
* by (its band axes, its ordinal colour) dims it, and any other selection
|
|
63
69
|
* filters it. 'filter': every selection filters it, even on a field it draws
|
|
64
70
|
* by, so its aggregates are recomputed for the subset (top N within a region).
|
|
71
|
+
* 'ignore': no selection filters or dims it; context, such as the whole
|
|
72
|
+
* drawn behind a filtered part.
|
|
65
73
|
*/
|
|
66
|
-
export type SelectionResponse = 'auto' | 'filter';
|
|
74
|
+
export type SelectionResponse = 'auto' | 'filter' | 'ignore';
|
|
67
75
|
export { NO_GROUP };
|
|
68
|
-
/**
|
|
76
|
+
/**
|
|
77
|
+
* Whether a selection can dim the mark: only under 'auto'. A 'filter' mark is
|
|
78
|
+
* filtered instead, and an 'ignore' mark neither.
|
|
79
|
+
*/
|
|
80
|
+
export declare function dimsBySelection(response: SelectionResponse | undefined): boolean;
|
|
81
|
+
/** A mark's reads under its selection response: none for a mark that never dims. */
|
|
69
82
|
export declare function readsForResponse(response: SelectionResponse | undefined, reads: readonly string[]): readonly string[];
|
|
70
|
-
/** The group index a mark's shader reads activity with: NO_GROUP for
|
|
83
|
+
/** The group index a mark's shader reads activity with: NO_GROUP for a mark that never dims. */
|
|
71
84
|
export declare function groupIndexForResponse(response: SelectionResponse | undefined, groupIndex: number): number;
|
|
72
85
|
/**
|
|
73
|
-
* The WGSL activity of a renderer that reads
|
|
74
|
-
* parallel coordinates):
|
|
75
|
-
*
|
|
76
|
-
*
|
|
86
|
+
* The WGSL activity of a renderer that reads no band axis (lines, areas,
|
|
87
|
+
* parallel coordinates): its colour activity and, for lines and areas, its
|
|
88
|
+
* series activity, 1.0 for each the table says it does not read.
|
|
89
|
+
*
|
|
90
|
+
* `series` is markColorActivity's first three arguments for the series scale,
|
|
91
|
+
* the same lookup as colour on another scale and buffer. The mark passes mode
|
|
92
|
+
* 0 when it has no `z` of its own, so the read returns 1.0 before loading
|
|
93
|
+
* anything. The two combine by `min`, the least active wins, as in
|
|
94
|
+
* markActivity: a series on the colour field cannot dim twice.
|
|
95
|
+
*
|
|
96
|
+
* Throws for a renderer that reads a band axis, whose call is
|
|
97
|
+
* markActivityWGSL, and for one that reads a series it was given no
|
|
98
|
+
* arguments for.
|
|
99
|
+
*/
|
|
100
|
+
export declare function connectedActivityWGSL(reads: ActivityReads, args: {
|
|
101
|
+
color: string;
|
|
102
|
+
series?: string;
|
|
103
|
+
group: string;
|
|
104
|
+
}): string;
|
|
105
|
+
/**
|
|
106
|
+
* The activity of an Other row: the same terms as markActivityWGSL without the
|
|
107
|
+
* band axes', and without colour's when colour is the band's own field
|
|
108
|
+
* (`skipColor`, a WGSL bool). Those read the Other bucket's own fade, and the
|
|
109
|
+
* bar's split already shows how much of it is selected (Rects); multiplying
|
|
110
|
+
* them in as well would dim it twice. Activity on any other field stays.
|
|
77
111
|
*/
|
|
78
|
-
export declare function
|
|
112
|
+
export declare function otherRowActivityWGSL(reads: ActivityReads, args: {
|
|
79
113
|
color: string;
|
|
80
114
|
group: string;
|
|
115
|
+
skipColor: string;
|
|
81
116
|
}): string;
|
|
82
117
|
/**
|
|
83
118
|
* The WGSL `markActivity(...)` call for `reads`: each activity the renderer
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Which selection activities a mark reads: its ordinal colour, its band x,
|
|
3
|
-
* its band y. One answer per renderer, used
|
|
3
|
+
* its band y, and a line's or area's series. One answer per renderer, used
|
|
4
|
+
* twice:
|
|
4
5
|
*
|
|
5
6
|
* - The renderer builds its shader's `markActivity` call from it, so a read
|
|
6
7
|
* the table does not list is passed as 1.0 and cannot happen.
|
|
@@ -20,12 +21,14 @@
|
|
|
20
21
|
* axis, belongs to no category on it, and must not dim by it.
|
|
21
22
|
*/
|
|
22
23
|
import { NO_GROUP } from '../../gpu/identity-slot-packing';
|
|
23
|
-
const ALL = { color: true, x: true, y: true };
|
|
24
|
-
const
|
|
24
|
+
const ALL = { color: true, x: true, y: true, series: false };
|
|
25
|
+
const CONNECTED = { color: true, x: false, y: false, series: true };
|
|
26
|
+
const COLOR_ONLY = { color: true, x: false, y: false, series: false };
|
|
25
27
|
/**
|
|
26
28
|
* What a renderer reads. `hasExtent` is a rule's: RuleX with y1/y2, RuleY with
|
|
27
|
-
* x1/x2. Lines
|
|
28
|
-
* a band axis spans its categories.
|
|
29
|
+
* x1/x2. Lines and areas dim by colour and by series (`z`), never by a band
|
|
30
|
+
* axis: a line over a band axis spans its categories. Parallel coordinates
|
|
31
|
+
* have no `z` and dim by colour only.
|
|
29
32
|
*/
|
|
30
33
|
export function activityReads(renderer, hasExtent = false) {
|
|
31
34
|
switch (renderer) {
|
|
@@ -34,11 +37,12 @@ export function activityReads(renderer, hasExtent = false) {
|
|
|
34
37
|
case 'text':
|
|
35
38
|
return ALL;
|
|
36
39
|
case 'rulex':
|
|
37
|
-
return { color: true, x: true, y: hasExtent };
|
|
40
|
+
return { color: true, x: true, y: hasExtent, series: false };
|
|
38
41
|
case 'ruley':
|
|
39
|
-
return { color: true, x: hasExtent, y: true };
|
|
42
|
+
return { color: true, x: hasExtent, y: true, series: false };
|
|
40
43
|
case 'lines':
|
|
41
44
|
case 'areas':
|
|
45
|
+
return CONNECTED;
|
|
42
46
|
case 'parallel':
|
|
43
47
|
return COLOR_ONLY;
|
|
44
48
|
}
|
|
@@ -85,7 +89,8 @@ export function rendererForMark(markType) {
|
|
|
85
89
|
* sorted, from what its renderer reads and the identity key of each of its
|
|
86
90
|
* categorical scales (null for a channel with no such scale, or a scale with
|
|
87
91
|
* no identity: a field with no identity has no activity to dim by, so a
|
|
88
|
-
* selection on it filters the mark).
|
|
92
|
+
* selection on it filters the mark). `series` is null unless the mark has a
|
|
93
|
+
* `z` of its own; a series that is the colour field is already in `color`.
|
|
89
94
|
*/
|
|
90
95
|
export function readsFor(reads, keys) {
|
|
91
96
|
const out = [];
|
|
@@ -95,6 +100,8 @@ export function readsFor(reads, keys) {
|
|
|
95
100
|
out.push(keys.x);
|
|
96
101
|
if (reads.y && keys.y)
|
|
97
102
|
out.push(keys.y);
|
|
103
|
+
if (reads.series && keys.series)
|
|
104
|
+
out.push(keys.series);
|
|
98
105
|
if (out.length === 0)
|
|
99
106
|
return NO_READS;
|
|
100
107
|
return [...new Set(out)].sort();
|
|
@@ -102,24 +109,59 @@ export function readsFor(reads, keys) {
|
|
|
102
109
|
/** A mark that reads no activity. Shared, so its reads never look changed. */
|
|
103
110
|
export const NO_READS = [];
|
|
104
111
|
export { NO_GROUP };
|
|
105
|
-
/**
|
|
112
|
+
/**
|
|
113
|
+
* Whether a selection can dim the mark: only under 'auto'. A 'filter' mark is
|
|
114
|
+
* filtered instead, and an 'ignore' mark neither.
|
|
115
|
+
*/
|
|
116
|
+
export function dimsBySelection(response) {
|
|
117
|
+
return response !== 'filter' && response !== 'ignore';
|
|
118
|
+
}
|
|
119
|
+
/** A mark's reads under its selection response: none for a mark that never dims. */
|
|
106
120
|
export function readsForResponse(response, reads) {
|
|
107
|
-
return response
|
|
121
|
+
return dimsBySelection(response) ? reads : NO_READS;
|
|
108
122
|
}
|
|
109
|
-
/** The group index a mark's shader reads activity with: NO_GROUP for
|
|
123
|
+
/** The group index a mark's shader reads activity with: NO_GROUP for a mark that never dims. */
|
|
110
124
|
export function groupIndexForResponse(response, groupIndex) {
|
|
111
|
-
return response
|
|
125
|
+
return dimsBySelection(response) ? groupIndex : NO_GROUP;
|
|
112
126
|
}
|
|
113
127
|
/**
|
|
114
|
-
* The WGSL activity of a renderer that reads
|
|
115
|
-
* parallel coordinates):
|
|
116
|
-
*
|
|
117
|
-
*
|
|
128
|
+
* The WGSL activity of a renderer that reads no band axis (lines, areas,
|
|
129
|
+
* parallel coordinates): its colour activity and, for lines and areas, its
|
|
130
|
+
* series activity, 1.0 for each the table says it does not read.
|
|
131
|
+
*
|
|
132
|
+
* `series` is markColorActivity's first three arguments for the series scale,
|
|
133
|
+
* the same lookup as colour on another scale and buffer. The mark passes mode
|
|
134
|
+
* 0 when it has no `z` of its own, so the read returns 1.0 before loading
|
|
135
|
+
* anything. The two combine by `min`, the least active wins, as in
|
|
136
|
+
* markActivity: a series on the colour field cannot dim twice.
|
|
137
|
+
*
|
|
138
|
+
* Throws for a renderer that reads a band axis, whose call is
|
|
139
|
+
* markActivityWGSL, and for one that reads a series it was given no
|
|
140
|
+
* arguments for.
|
|
118
141
|
*/
|
|
119
|
-
export function
|
|
142
|
+
export function connectedActivityWGSL(reads, args) {
|
|
120
143
|
if (reads.x || reads.y)
|
|
121
|
-
throw new Error('
|
|
122
|
-
|
|
144
|
+
throw new Error('connectedActivityWGSL: this renderer reads a band axis');
|
|
145
|
+
if (reads.series && !args.series) {
|
|
146
|
+
throw new Error('connectedActivityWGSL: this renderer reads a series; pass its arguments');
|
|
147
|
+
}
|
|
148
|
+
const color = reads.color ? `markColorActivity(${args.color}, ${args.group})` : '1.0';
|
|
149
|
+
if (!reads.series)
|
|
150
|
+
return color;
|
|
151
|
+
return `min(${color}, markColorActivity(${args.series}, ${args.group}))`;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* The activity of an Other row: the same terms as markActivityWGSL without the
|
|
155
|
+
* band axes', and without colour's when colour is the band's own field
|
|
156
|
+
* (`skipColor`, a WGSL bool). Those read the Other bucket's own fade, and the
|
|
157
|
+
* bar's split already shows how much of it is selected (Rects); multiplying
|
|
158
|
+
* them in as well would dim it twice. Activity on any other field stays.
|
|
159
|
+
*/
|
|
160
|
+
export function otherRowActivityWGSL(reads, args) {
|
|
161
|
+
const color = reads.color
|
|
162
|
+
? `select(markColorActivity(${args.color}, ${args.group}), 1.0, ${args.skipColor})`
|
|
163
|
+
: '1.0';
|
|
164
|
+
return `markActivity(${color}, 1.0, 1.0)`;
|
|
123
165
|
}
|
|
124
166
|
/**
|
|
125
167
|
* The WGSL `markActivity(...)` call for `reads`: each activity the renderer
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
export declare const PARALLEL_MAX_AXES = 16;
|
|
14
14
|
export declare const UNIFORM_BYTES: {
|
|
15
15
|
readonly dotsMarkConstants: 48;
|
|
16
|
-
readonly rectsMarkConstants:
|
|
16
|
+
readonly rectsMarkConstants: 64;
|
|
17
17
|
readonly ruleXMarkConstants: 48;
|
|
18
18
|
readonly ruleYMarkConstants: 48;
|
|
19
19
|
readonly linesMarkConstants: 64;
|