@fjader/svelte 0.2.4 → 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 +1 -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 +4 -2
- package/dist/components/axes/AxisCenter.svelte +4 -2
- package/dist/components/axes/AxisLeft.svelte +4 -2
- package/dist/components/axes/BandAxisTicks.svelte +3 -2
- package/dist/components/charts/ChartCell.svelte +32 -5
- package/dist/components/charts/ChartCell.svelte.d.ts +9 -0
- package/dist/components/charts/ChartContainer.svelte +45 -3
- package/dist/components/charts/ChartContainer.svelte.d.ts +7 -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/marks/AreaMarkX.svelte +16 -4
- package/dist/components/marks/AreaMarkY.svelte +16 -4
- package/dist/components/marks/BarMarkX.svelte +7 -3
- package/dist/components/marks/BarMarkY.svelte +7 -3
- package/dist/components/marks/DotsMark.svelte +6 -3
- package/dist/components/marks/LineMark.svelte +11 -8
- package/dist/components/marks/ParallelCoordinatesMark.svelte +7 -2
- package/dist/components/marks/ParallelCoordinatesMark.svelte.d.ts +2 -0
- package/dist/components/marks/RectMark.svelte +6 -3
- package/dist/components/marks/RectXMark.svelte +7 -3
- package/dist/components/marks/RectYMark.svelte +7 -3
- package/dist/components/marks/RuleMarkX.svelte +30 -26
- package/dist/components/marks/RuleMarkY.svelte +30 -26
- package/dist/components/marks/TextMark.svelte +44 -5
- package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.d.ts +16 -0
- package/dist/components/marks/lifecycle/MarkLifecycleV2.svelte.js +398 -54
- package/dist/components/marks/lifecycle/domain-queries.d.ts +11 -2
- package/dist/components/marks/lifecycle/domain-queries.js +33 -6
- package/dist/components/marks/lifecycle/domain-registration.d.ts +6 -1
- package/dist/components/marks/lifecycle/domain-registration.js +15 -14
- package/dist/components/marks/lifecycle/other-rows.svelte.d.ts +9 -1
- package/dist/components/marks/lifecycle/other-rows.svelte.js +2 -2
- package/dist/components/marks/lifecycle/query-builder.d.ts +27 -2
- package/dist/components/marks/lifecycle/query-builder.js +23 -20
- 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 +3 -0
- 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 +1 -1
- 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 +51 -11
- package/dist/components/rendering/Rects.svelte.d.ts +16 -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 +41 -24
- package/dist/components/rendering/activity-reads.js +54 -31
- 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 +7 -0
- 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 -2
- package/dist/gpu/MorphedChannels.js +33 -11
- package/dist/gpu/ScaleTemplateSystem.d.ts +20 -2
- package/dist/gpu/ScaleTemplateSystem.js +58 -2
- package/dist/index.d.ts +17 -4
- package/dist/index.js +19 -4
- package/dist/interactors/TooltipManager.svelte.js +14 -5
- 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 +2 -3
- package/dist/query-engine/FieldActivity.svelte.js +1 -2
- 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 +671 -41
- package/dist/query-engine/categorical-identity.d.ts +34 -8
- package/dist/query-engine/categorical-identity.js +138 -73
- 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 +28 -1
- package/dist/query-engine/preagg/plan.js +128 -8
- 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/scales/BandScaleState.svelte.d.ts +9 -1
- package/dist/scales/BandScaleState.svelte.js +16 -5
- 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 +41 -13
- package/dist/sql/bin.d.ts +25 -0
- package/dist/sql/bin.js +108 -5
- package/dist/transforms/TransformCompiler.d.ts +10 -0
- package/dist/transforms/TransformCompiler.js +26 -0
- package/dist/transforms/index.js +144 -24
- package/dist/types.d.ts +136 -2
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { activityReads,
|
|
2
|
+
import { activityReads, connectedActivityWGSL } from './activity-reads';
|
|
3
3
|
import { UNIFORM_BYTES } from './uniform-sizes';
|
|
4
4
|
import { getContext, onMount, onDestroy } from 'svelte';
|
|
5
5
|
import { RendererHost } from './RendererHost.svelte';
|
|
@@ -38,7 +38,10 @@
|
|
|
38
38
|
DOT_RADIUS: 36, // f32
|
|
39
39
|
SHOW_BOTTOM_DOTS: 40, // u32 (0 or 1)
|
|
40
40
|
FULL_DOMAIN_SPAN: 44, // f32
|
|
41
|
-
GROUP_INDEX: 48 // u32
|
|
41
|
+
GROUP_INDEX: 48, // u32
|
|
42
|
+
ACTIVITY_SERIES_MODE: 52, // u32
|
|
43
|
+
ACTIVITY_SERIES_SCALE_INDEX: 56, // u32
|
|
44
|
+
ENTRANCE_AXIS: 60 // u32 (0 fades, 1 grows along x, 2 along y)
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
interface Props {
|
|
@@ -60,8 +63,20 @@
|
|
|
60
63
|
colorScaleIndex?: number;
|
|
61
64
|
/** The page-wide index of this mark's filter group: which run of a field's activity block it reads. */
|
|
62
65
|
groupIndex?: number;
|
|
66
|
+
/**
|
|
67
|
+
* The series scale selection activity is also read through, from
|
|
68
|
+
* `seriesData`: mode 1 and its index when the mark groups by a `z` of
|
|
69
|
+
* its own, mode 0 (no read) otherwise. MarkSeries decides.
|
|
70
|
+
*/
|
|
71
|
+
activitySeriesMode?: number;
|
|
72
|
+
activitySeriesScaleIndex?: number;
|
|
63
73
|
constantColor?: [number, number, number, number];
|
|
64
74
|
markId?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Whether the area grows from 0 along its measure axis when its chart
|
|
77
|
+
* enters. False fades it in, for a band with bounds of its own.
|
|
78
|
+
*/
|
|
79
|
+
grow?: boolean;
|
|
65
80
|
}
|
|
66
81
|
|
|
67
82
|
let {
|
|
@@ -82,8 +97,11 @@
|
|
|
82
97
|
colorMode = 0,
|
|
83
98
|
colorScaleIndex = 0,
|
|
84
99
|
groupIndex = 0,
|
|
100
|
+
activitySeriesMode = 0,
|
|
101
|
+
activitySeriesScaleIndex = 0,
|
|
85
102
|
constantColor = DEFAULT_FILL_COLOR,
|
|
86
|
-
markId = ''
|
|
103
|
+
markId = '',
|
|
104
|
+
grow = false
|
|
87
105
|
}: Props = $props();
|
|
88
106
|
|
|
89
107
|
const chartContext = getContext<ChartContext>('chart');
|
|
@@ -152,9 +170,11 @@
|
|
|
152
170
|
showBottomDots: u32,
|
|
153
171
|
fullDomainSpan: f32,
|
|
154
172
|
groupIndex: u32, // Page-wide filter group index, for activity reads
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
173
|
+
// The series scale selection activity is also read through, for a z of
|
|
174
|
+
// its own; mode 0 reads nothing.
|
|
175
|
+
activitySeriesMode: u32,
|
|
176
|
+
activitySeriesScaleIndex: u32,
|
|
177
|
+
entranceAxis: u32 // 0 fades in, 1 grows along x, 2 along y
|
|
158
178
|
};
|
|
159
179
|
@group(1) @binding(5) var<uniform> markConstants: MarkConstants;
|
|
160
180
|
|
|
@@ -186,6 +206,12 @@
|
|
|
186
206
|
}
|
|
187
207
|
}
|
|
188
208
|
|
|
209
|
+
// A point projected to pixels as it is during the chart's entrance: pulled
|
|
210
|
+
// toward 0 on the measure axis while the area grows.
|
|
211
|
+
fn enterPx(p: vec2<f32>) -> vec2<f32> {
|
|
212
|
+
return entrancePosition(projectToPixels(p), markConstants.entranceAxis);
|
|
213
|
+
}
|
|
214
|
+
|
|
189
215
|
const DISCARD_POS = vec4<f32>(2.0, 2.0, 2.0, 1.0);
|
|
190
216
|
|
|
191
217
|
@vertex
|
|
@@ -220,7 +246,7 @@
|
|
|
220
246
|
output.position = DISCARD_POS;
|
|
221
247
|
return output;
|
|
222
248
|
}
|
|
223
|
-
let center =
|
|
249
|
+
let center = enterPx(makePoint(dim, boundary));
|
|
224
250
|
|
|
225
251
|
var circleR: f32;
|
|
226
252
|
if (markConstants.dotRadius < 0.0) {
|
|
@@ -254,9 +280,11 @@
|
|
|
254
280
|
var output: VertexOutput;
|
|
255
281
|
output.position = pixelsToClip(pos);
|
|
256
282
|
output.colorValue = colorValues[instanceIdx];
|
|
257
|
-
output.alpha = selectionDim(
|
|
258
|
-
${
|
|
283
|
+
output.alpha = entranceAlpha(markConstants.entranceAxis) * selectionDim(
|
|
284
|
+
${connectedActivityWGSL(ACTIVITY_READS, {
|
|
259
285
|
color: 'markConstants.colorMode, markConstants.colorScaleIndex, colorValues[instanceIdx]',
|
|
286
|
+
series:
|
|
287
|
+
'markConstants.activitySeriesMode, markConstants.activitySeriesScaleIndex, seriesValues[instanceIdx]',
|
|
260
288
|
group: 'markConstants.groupIndex'
|
|
261
289
|
})}
|
|
262
290
|
);
|
|
@@ -304,10 +332,10 @@
|
|
|
304
332
|
}
|
|
305
333
|
|
|
306
334
|
// Project segment endpoints for adaptive resolution
|
|
307
|
-
let topPxCurr =
|
|
308
|
-
let topPxNext =
|
|
309
|
-
let botPxCurr =
|
|
310
|
-
let botPxNext =
|
|
335
|
+
let topPxCurr = enterPx(makePoint(dimCurr, topCurr));
|
|
336
|
+
let topPxNext = enterPx(makePoint(dimNext, topNext));
|
|
337
|
+
let botPxCurr = enterPx(makePoint(dimCurr, botCurr));
|
|
338
|
+
let botPxNext = enterPx(makePoint(dimNext, botNext));
|
|
311
339
|
|
|
312
340
|
// Adaptive sub-segment resolution: more segments for longer pixel spans.
|
|
313
341
|
// Use the longer of top/bottom chord for resolution calculation.
|
|
@@ -336,10 +364,10 @@
|
|
|
336
364
|
let dimPrev = dimValues[prevIdx];
|
|
337
365
|
let dimAfter = dimValues[afterIdx];
|
|
338
366
|
|
|
339
|
-
let topPxPrev =
|
|
340
|
-
let topPxAfter =
|
|
341
|
-
let botPxPrev =
|
|
342
|
-
let botPxAfter =
|
|
367
|
+
let topPxPrev = enterPx(makePoint(dimPrev, topValues[prevIdx]));
|
|
368
|
+
let topPxAfter = enterPx(makePoint(dimAfter, topValues[afterIdx]));
|
|
369
|
+
let botPxPrev = enterPx(makePoint(dimPrev, bottomValues[prevIdx]));
|
|
370
|
+
let botPxAfter = enterPx(makePoint(dimAfter, bottomValues[afterIdx]));
|
|
343
371
|
|
|
344
372
|
// Compute t for this vertex from effective resolution (not geometry buffer)
|
|
345
373
|
let subSegSize = 1.0 / f32(effectiveRes);
|
|
@@ -359,9 +387,11 @@
|
|
|
359
387
|
var output: VertexOutput;
|
|
360
388
|
output.position = pixelsToClip(finalPos);
|
|
361
389
|
output.colorValue = colorValues[currIdx];
|
|
362
|
-
output.alpha = markConstants.fillOpacity * selectionDim(
|
|
363
|
-
${
|
|
390
|
+
output.alpha = markConstants.fillOpacity * entranceAlpha(markConstants.entranceAxis) * selectionDim(
|
|
391
|
+
${connectedActivityWGSL(ACTIVITY_READS, {
|
|
364
392
|
color: 'markConstants.colorMode, markConstants.colorScaleIndex, colorValues[currIdx]',
|
|
393
|
+
series:
|
|
394
|
+
'markConstants.activitySeriesMode, markConstants.activitySeriesScaleIndex, seriesValues[currIdx]',
|
|
365
395
|
group: 'markConstants.groupIndex'
|
|
366
396
|
})}
|
|
367
397
|
);
|
|
@@ -471,7 +501,15 @@
|
|
|
471
501
|
view.setUint32(UNIFORM_OFFSETS.COLOR_MODE, colorMode, LE);
|
|
472
502
|
view.setUint32(UNIFORM_OFFSETS.COLOR_SCALE_INDEX, colorScaleIndex, LE);
|
|
473
503
|
view.setUint32(UNIFORM_OFFSETS.GROUP_INDEX, groupIndex, LE);
|
|
504
|
+
view.setUint32(UNIFORM_OFFSETS.ACTIVITY_SERIES_MODE, activitySeriesMode, LE);
|
|
505
|
+
view.setUint32(UNIFORM_OFFSETS.ACTIVITY_SERIES_SCALE_INDEX, activitySeriesScaleIndex, LE);
|
|
474
506
|
view.setUint32(UNIFORM_OFFSETS.ORIENTATION, orientation === 'horizontal' ? 1 : 0, LE);
|
|
507
|
+
// Grows along the boundary axis: y for a vertical area, x for a horizontal one.
|
|
508
|
+
view.setUint32(
|
|
509
|
+
UNIFORM_OFFSETS.ENTRANCE_AXIS,
|
|
510
|
+
grow ? (orientation === 'horizontal' ? 1 : 2) : 0,
|
|
511
|
+
LE
|
|
512
|
+
);
|
|
475
513
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 0, constantColor[0], LE);
|
|
476
514
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 4, constantColor[1], LE);
|
|
477
515
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 8, constantColor[2], LE);
|
|
@@ -18,8 +18,20 @@ interface Props {
|
|
|
18
18
|
colorScaleIndex?: number;
|
|
19
19
|
/** The page-wide index of this mark's filter group: which run of a field's activity block it reads. */
|
|
20
20
|
groupIndex?: number;
|
|
21
|
+
/**
|
|
22
|
+
* The series scale selection activity is also read through, from
|
|
23
|
+
* `seriesData`: mode 1 and its index when the mark groups by a `z` of
|
|
24
|
+
* its own, mode 0 (no read) otherwise. MarkSeries decides.
|
|
25
|
+
*/
|
|
26
|
+
activitySeriesMode?: number;
|
|
27
|
+
activitySeriesScaleIndex?: number;
|
|
21
28
|
constantColor?: [number, number, number, number];
|
|
22
29
|
markId?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Whether the area grows from 0 along its measure axis when its chart
|
|
32
|
+
* enters. False fades it in, for a band with bounds of its own.
|
|
33
|
+
*/
|
|
34
|
+
grow?: boolean;
|
|
23
35
|
}
|
|
24
36
|
declare const Areas: import("svelte").Component<Props, {}, "">;
|
|
25
37
|
type Areas = ReturnType<typeof Areas>;
|
|
@@ -59,7 +59,7 @@ export declare class BaseGPURenderer {
|
|
|
59
59
|
*/
|
|
60
60
|
writeMorphed(bandAxis: 'x' | 'y', bandIds: ArrayLike<number>, channels: readonly (readonly [number, AllowSharedBufferSource])[],
|
|
61
61
|
/** Bindings that land at once rather than travel (see MorphedChannels.write). */
|
|
62
|
-
land?: readonly number[]): void;
|
|
62
|
+
land?: readonly number[] | 'all'): void;
|
|
63
63
|
/**
|
|
64
64
|
* Write data to a uniform binding.
|
|
65
65
|
*/
|
|
@@ -43,6 +43,12 @@
|
|
|
43
43
|
alphaData: Float32Array | null;
|
|
44
44
|
facetData?: Float32Array | null;
|
|
45
45
|
dataVersion: number;
|
|
46
|
+
/**
|
|
47
|
+
* The data version whose first write lands without morphing, or 0: a
|
|
48
|
+
* catch-up result (MarkLifecycleV2.landsFor). Later writes of that version
|
|
49
|
+
* animate as usual.
|
|
50
|
+
*/
|
|
51
|
+
landsFor?: number;
|
|
46
52
|
zIndex?: number;
|
|
47
53
|
colorMode?: number;
|
|
48
54
|
colorScaleIndex?: number;
|
|
@@ -74,6 +80,7 @@
|
|
|
74
80
|
alphaData,
|
|
75
81
|
facetData = null,
|
|
76
82
|
dataVersion,
|
|
83
|
+
landsFor = 0,
|
|
77
84
|
zIndex = 0,
|
|
78
85
|
colorMode = 0,
|
|
79
86
|
colorScaleIndex = 0,
|
|
@@ -188,7 +195,7 @@
|
|
|
188
195
|
output.colorValue = colorValue;
|
|
189
196
|
output.uv = quadPosition;
|
|
190
197
|
output.radius = displayRadius;
|
|
191
|
-
output.alpha = alpha * selectionDim(
|
|
198
|
+
output.alpha = alpha * entranceAlpha(0u) * selectionDim(
|
|
192
199
|
${markActivityWGSL(ACTIVITY_READS, {
|
|
193
200
|
color: 'markConstants.colorMode, markConstants.colorScaleIndex, colorValue',
|
|
194
201
|
x: 'x',
|
|
@@ -260,6 +267,18 @@
|
|
|
260
267
|
|
|
261
268
|
// --- WRITING EFFECTS ---
|
|
262
269
|
|
|
270
|
+
// Whether this write lands: the first of the catch-up's data version
|
|
271
|
+
// (landsFor). Plain, not $state: only the write effect reads and sets it.
|
|
272
|
+
// Assumes a catch-up result is ONE morph write: should it ever take two
|
|
273
|
+
// (values, then band ids after the instant layout), the second springs.
|
|
274
|
+
// A morph SPRING right after a morph snap on a return points here.
|
|
275
|
+
let lastMorphedVersion = -1;
|
|
276
|
+
function landsNow(): boolean {
|
|
277
|
+
const first = dataVersion !== lastMorphedVersion;
|
|
278
|
+
lastMorphedVersion = dataVersion;
|
|
279
|
+
return first && landsFor !== 0 && landsFor === dataVersion;
|
|
280
|
+
}
|
|
281
|
+
|
|
263
282
|
// The measure axis's single channel morphs, as ONE write per data update,
|
|
264
283
|
// so one update starts one transition. The band's ids go with it: they are
|
|
265
284
|
// how a row set that is not the one being animated gets noticed and snapped.
|
|
@@ -269,8 +288,9 @@
|
|
|
269
288
|
// design question rather than a consequence of this one.
|
|
270
289
|
$effect(() => {
|
|
271
290
|
if (!renderer?.resourcesCreated || !bandAxis) return;
|
|
272
|
-
|
|
273
|
-
|
|
291
|
+
const land = landsNow() ? 'all' : undefined;
|
|
292
|
+
if (bandAxis === 'x') renderer.writeMorphed('x', xData, [[BINDINGS.Y, yData]], land);
|
|
293
|
+
else renderer.writeMorphed('y', yData, [[BINDINGS.X, xData]], land);
|
|
274
294
|
});
|
|
275
295
|
$effect(() => {
|
|
276
296
|
if (renderer?.resourcesCreated && !morphX) renderer.writeAttribute(BINDINGS.X, xData);
|
|
@@ -6,6 +6,12 @@ interface Props {
|
|
|
6
6
|
alphaData: Float32Array | null;
|
|
7
7
|
facetData?: Float32Array | null;
|
|
8
8
|
dataVersion: number;
|
|
9
|
+
/**
|
|
10
|
+
* The data version whose first write lands without morphing, or 0: a
|
|
11
|
+
* catch-up result (MarkLifecycleV2.landsFor). Later writes of that version
|
|
12
|
+
* animate as usual.
|
|
13
|
+
*/
|
|
14
|
+
landsFor?: number;
|
|
9
15
|
zIndex?: number;
|
|
10
16
|
colorMode?: number;
|
|
11
17
|
colorScaleIndex?: number;
|
|
@@ -44,6 +44,11 @@
|
|
|
44
44
|
* way a bar's height is. Omitted, every line is fully drawn.
|
|
45
45
|
*/
|
|
46
46
|
alpha?: Float32Array | null;
|
|
47
|
+
/**
|
|
48
|
+
* The band layout whose first opacity write lands without morphing, or 0
|
|
49
|
+
* (a layout that landed at once; see BandScaleState.slotsLandedLayout).
|
|
50
|
+
*/
|
|
51
|
+
landsFor?: number;
|
|
47
52
|
/** The band axis these lines belong to, when `alpha` should morph. */
|
|
48
53
|
bandAxis?: 'x' | 'y' | null;
|
|
49
54
|
color?: [number, number, number, number];
|
|
@@ -55,6 +60,7 @@
|
|
|
55
60
|
axis,
|
|
56
61
|
positions,
|
|
57
62
|
alpha = null,
|
|
63
|
+
landsFor = 0,
|
|
58
64
|
bandAxis = null,
|
|
59
65
|
color = [0.8, 0.8, 0.8, 0.3],
|
|
60
66
|
lineWidth = 1,
|
|
@@ -175,9 +181,15 @@ ${placement}
|
|
|
175
181
|
// the positions are that id list — which is what writeMorphed checks rows
|
|
176
182
|
// against.
|
|
177
183
|
const morphs = $derived(!!bandAxis && !!alpha && alpha.length === positions?.length);
|
|
184
|
+
// The landed layout last written; plain, read and set by the write alone.
|
|
185
|
+
let lastLandedLayout = 0;
|
|
178
186
|
$effect(() => {
|
|
179
187
|
if (!renderer?.resourcesCreated || !morphs) return;
|
|
180
|
-
|
|
188
|
+
// Only the first write after that layout lands: the opacity it changed.
|
|
189
|
+
const first = landsFor !== lastLandedLayout;
|
|
190
|
+
lastLandedLayout = landsFor;
|
|
191
|
+
const land = first && landsFor !== 0 ? 'all' : undefined;
|
|
192
|
+
renderer.writeMorphed(bandAxis!, positions, [[BINDINGS.ALPHA, alpha!]], land);
|
|
181
193
|
});
|
|
182
194
|
|
|
183
195
|
// Otherwise every line is fully drawn. Keyed on the line COUNT alone, because
|
|
@@ -9,6 +9,11 @@ interface Props {
|
|
|
9
9
|
* way a bar's height is. Omitted, every line is fully drawn.
|
|
10
10
|
*/
|
|
11
11
|
alpha?: Float32Array | null;
|
|
12
|
+
/**
|
|
13
|
+
* The band layout whose first opacity write lands without morphing, or 0
|
|
14
|
+
* (a layout that landed at once; see BandScaleState.slotsLandedLayout).
|
|
15
|
+
*/
|
|
16
|
+
landsFor?: number;
|
|
12
17
|
/** The band axis these lines belong to, when `alpha` should morph. */
|
|
13
18
|
bandAxis?: 'x' | 'y' | null;
|
|
14
19
|
color?: [number, number, number, number];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { activityReads,
|
|
2
|
+
import { activityReads, connectedActivityWGSL } from './activity-reads';
|
|
3
3
|
import { UNIFORM_BYTES } from './uniform-sizes';
|
|
4
4
|
import { getContext, onMount, onDestroy } from 'svelte';
|
|
5
5
|
import { RendererHost } from './RendererHost.svelte';
|
|
@@ -38,7 +38,10 @@
|
|
|
38
38
|
GLOBAL_ALPHA: 36, // f32
|
|
39
39
|
GROUP_INDEX: 40, // u32
|
|
40
40
|
ACTIVITY_COLOR_MODE: 44, // u32
|
|
41
|
-
ACTIVITY_COLOR_SCALE_INDEX: 48 // u32
|
|
41
|
+
ACTIVITY_COLOR_SCALE_INDEX: 48, // u32
|
|
42
|
+
ACTIVITY_SERIES_MODE: 52, // u32
|
|
43
|
+
ACTIVITY_SERIES_SCALE_INDEX: 56, // u32
|
|
44
|
+
ENTRANCE_AXIS: 60 // u32 (0 fades, 1 grows along x, 2 along y)
|
|
42
45
|
};
|
|
43
46
|
|
|
44
47
|
interface Props {
|
|
@@ -63,11 +66,23 @@
|
|
|
63
66
|
*/
|
|
64
67
|
activityColorMode?: number | null;
|
|
65
68
|
activityColorScaleIndex?: number | null;
|
|
69
|
+
/**
|
|
70
|
+
* The series scale selection activity is also read through, from
|
|
71
|
+
* `seriesData`: mode 1 and its index when the mark groups by a `z` of
|
|
72
|
+
* its own, mode 0 (no read) otherwise. MarkSeries decides.
|
|
73
|
+
*/
|
|
74
|
+
activitySeriesMode?: number;
|
|
75
|
+
activitySeriesScaleIndex?: number;
|
|
66
76
|
constantColor?: [number, number, number, number];
|
|
67
77
|
m4Decimator?: M4Decimator | null;
|
|
68
78
|
dotsRung?: import('../../lod/DotsRung.svelte').DotsRung | null;
|
|
69
79
|
globalAlpha?: number;
|
|
70
80
|
markId?: string;
|
|
81
|
+
/**
|
|
82
|
+
* The axis this line grows along when its chart enters, or null to fade
|
|
83
|
+
* in. A line mark fades; an area's outline grows with its fill.
|
|
84
|
+
*/
|
|
85
|
+
grow?: 'x' | 'y' | null;
|
|
71
86
|
}
|
|
72
87
|
|
|
73
88
|
let {
|
|
@@ -86,11 +101,14 @@
|
|
|
86
101
|
groupIndex = 0,
|
|
87
102
|
activityColorMode = null,
|
|
88
103
|
activityColorScaleIndex = null,
|
|
104
|
+
activitySeriesMode = 0,
|
|
105
|
+
activitySeriesScaleIndex = 0,
|
|
89
106
|
constantColor = DEFAULT_STROKE_COLOR,
|
|
90
107
|
m4Decimator = null,
|
|
91
108
|
dotsRung = null,
|
|
92
109
|
globalAlpha = 1.0,
|
|
93
|
-
markId = ''
|
|
110
|
+
markId = '',
|
|
111
|
+
grow = null
|
|
94
112
|
}: Props = $props();
|
|
95
113
|
|
|
96
114
|
const chartContext = getContext<ChartContext>('chart');
|
|
@@ -164,10 +182,20 @@
|
|
|
164
182
|
// own colour by default; an area's outline, drawn in a constant stroke,
|
|
165
183
|
// reads its fill's so it dims with the fill.
|
|
166
184
|
activityColorMode: u32,
|
|
167
|
-
activityColorScaleIndex: u32
|
|
185
|
+
activityColorScaleIndex: u32,
|
|
186
|
+
// The series scale it is also read through, for a z of its own; mode 0
|
|
187
|
+
// reads nothing.
|
|
188
|
+
activitySeriesMode: u32,
|
|
189
|
+
activitySeriesScaleIndex: u32,
|
|
190
|
+
entranceAxis: u32 // 0 fades in, 1 grows along x, 2 along y
|
|
168
191
|
};
|
|
169
192
|
@group(1) @binding(4) var<uniform> markConstants: MarkConstants;
|
|
170
193
|
|
|
194
|
+
// A point projected to pixels as it is during the chart's entrance.
|
|
195
|
+
fn enterPx(p: vec2<f32>) -> vec2<f32> {
|
|
196
|
+
return entrancePosition(projectToPixels(p), markConstants.entranceAxis);
|
|
197
|
+
}
|
|
198
|
+
|
|
171
199
|
struct VertexOutput {
|
|
172
200
|
@builtin(position) position: vec4<f32>,
|
|
173
201
|
@location(0) colorValue: f32,
|
|
@@ -211,7 +239,7 @@
|
|
|
211
239
|
output.position = DISCARD_POS;
|
|
212
240
|
return output;
|
|
213
241
|
}
|
|
214
|
-
let center =
|
|
242
|
+
let center = enterPx(vec2<f32>(x, y));
|
|
215
243
|
|
|
216
244
|
// JS computes dotRadius via DotsRung. 0 = no dots. >0 = show at this size.
|
|
217
245
|
let circleR = select(halfWidth, markConstants.dotRadius * frameUniforms.devicePixelRatio,
|
|
@@ -221,10 +249,12 @@
|
|
|
221
249
|
var output: VertexOutput;
|
|
222
250
|
output.position = pixelsToClip(pos);
|
|
223
251
|
output.colorValue = colorValues[instanceIdx];
|
|
224
|
-
output.alpha = markConstants.globalAlpha * selectionDim(
|
|
225
|
-
${
|
|
252
|
+
output.alpha = markConstants.globalAlpha * entranceAlpha(markConstants.entranceAxis) * selectionDim(
|
|
253
|
+
${connectedActivityWGSL(ACTIVITY_READS, {
|
|
226
254
|
color:
|
|
227
255
|
'markConstants.activityColorMode, markConstants.activityColorScaleIndex, colorValues[instanceIdx]',
|
|
256
|
+
series:
|
|
257
|
+
'markConstants.activitySeriesMode, markConstants.activitySeriesScaleIndex, seriesValues[instanceIdx]',
|
|
228
258
|
group: 'markConstants.groupIndex'
|
|
229
259
|
})}
|
|
230
260
|
);
|
|
@@ -258,8 +288,8 @@
|
|
|
258
288
|
}
|
|
259
289
|
|
|
260
290
|
// Project segment endpoints to pixel space
|
|
261
|
-
let pCurr =
|
|
262
|
-
let pNext =
|
|
291
|
+
let pCurr = enterPx(vec2<f32>(xCurr, yCurr));
|
|
292
|
+
let pNext = enterPx(vec2<f32>(xNext, yNext));
|
|
263
293
|
|
|
264
294
|
// Adaptive sub-segment resolution: more segments for longer pixel spans.
|
|
265
295
|
// Fixed-resolution curves (linear, step) have CURVE_RESOLUTION <= 3;
|
|
@@ -286,8 +316,8 @@
|
|
|
286
316
|
nextIdx + 1u >= pointCount || seriesValues[nextIdx + 1u] != seriesNext);
|
|
287
317
|
|
|
288
318
|
// Project neighbor control points
|
|
289
|
-
let pPrev =
|
|
290
|
-
let pAfter =
|
|
319
|
+
let pPrev = enterPx(vec2<f32>(xValues[prevIdx], yValues[prevIdx]));
|
|
320
|
+
let pAfter = enterPx(vec2<f32>(xValues[afterIdx], yValues[afterIdx]));
|
|
291
321
|
|
|
292
322
|
// Compute t values from effective resolution (not geometry buffer)
|
|
293
323
|
let subSegSize = 1.0 / f32(effectiveRes);
|
|
@@ -322,10 +352,12 @@
|
|
|
322
352
|
var output: VertexOutput;
|
|
323
353
|
output.position = pixelsToClip(finalPos);
|
|
324
354
|
output.colorValue = colorValues[currIdx];
|
|
325
|
-
output.alpha = markConstants.globalAlpha * selectionDim(
|
|
326
|
-
${
|
|
355
|
+
output.alpha = markConstants.globalAlpha * entranceAlpha(markConstants.entranceAxis) * selectionDim(
|
|
356
|
+
${connectedActivityWGSL(ACTIVITY_READS, {
|
|
327
357
|
color:
|
|
328
358
|
'markConstants.activityColorMode, markConstants.activityColorScaleIndex, colorValues[currIdx]',
|
|
359
|
+
series:
|
|
360
|
+
'markConstants.activitySeriesMode, markConstants.activitySeriesScaleIndex, seriesValues[currIdx]',
|
|
329
361
|
group: 'markConstants.groupIndex'
|
|
330
362
|
})}
|
|
331
363
|
);
|
|
@@ -443,6 +475,9 @@
|
|
|
443
475
|
view.setUint32(UNIFORM_OFFSETS.GROUP_INDEX, groupIndex, LE);
|
|
444
476
|
view.setUint32(UNIFORM_OFFSETS.ACTIVITY_COLOR_MODE, activityMode, LE);
|
|
445
477
|
view.setUint32(UNIFORM_OFFSETS.ACTIVITY_COLOR_SCALE_INDEX, activityScale, LE);
|
|
478
|
+
view.setUint32(UNIFORM_OFFSETS.ACTIVITY_SERIES_MODE, activitySeriesMode, LE);
|
|
479
|
+
view.setUint32(UNIFORM_OFFSETS.ACTIVITY_SERIES_SCALE_INDEX, activitySeriesScaleIndex, LE);
|
|
480
|
+
view.setUint32(UNIFORM_OFFSETS.ENTRANCE_AXIS, grow === 'x' ? 1 : grow === 'y' ? 2 : 0, LE);
|
|
446
481
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 0, constantColor[0], LE);
|
|
447
482
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 4, constantColor[1], LE);
|
|
448
483
|
view.setFloat32(UNIFORM_OFFSETS.CONSTANT_COLOR + 8, constantColor[2], LE);
|
|
@@ -22,11 +22,23 @@ interface Props {
|
|
|
22
22
|
*/
|
|
23
23
|
activityColorMode?: number | null;
|
|
24
24
|
activityColorScaleIndex?: number | null;
|
|
25
|
+
/**
|
|
26
|
+
* The series scale selection activity is also read through, from
|
|
27
|
+
* `seriesData`: mode 1 and its index when the mark groups by a `z` of
|
|
28
|
+
* its own, mode 0 (no read) otherwise. MarkSeries decides.
|
|
29
|
+
*/
|
|
30
|
+
activitySeriesMode?: number;
|
|
31
|
+
activitySeriesScaleIndex?: number;
|
|
25
32
|
constantColor?: [number, number, number, number];
|
|
26
33
|
m4Decimator?: M4Decimator | null;
|
|
27
34
|
dotsRung?: import('../../lod/DotsRung.svelte').DotsRung | null;
|
|
28
35
|
globalAlpha?: number;
|
|
29
36
|
markId?: string;
|
|
37
|
+
/**
|
|
38
|
+
* The axis this line grows along when its chart enters, or null to fade
|
|
39
|
+
* in. A line mark fades; an area's outline grows with its fill.
|
|
40
|
+
*/
|
|
41
|
+
grow?: 'x' | 'y' | null;
|
|
30
42
|
}
|
|
31
43
|
declare const Lines: import("svelte").Component<Props, {}, "">;
|
|
32
44
|
type Lines = ReturnType<typeof Lines>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { activityReads,
|
|
2
|
+
import { activityReads, connectedActivityWGSL } from './activity-reads';
|
|
3
3
|
import { PARALLEL_MAX_AXES, UNIFORM_BYTES } from './uniform-sizes';
|
|
4
4
|
import { getContext, onMount, onDestroy } from 'svelte';
|
|
5
5
|
import { RendererHost } from './RendererHost.svelte';
|
|
@@ -199,8 +199,8 @@
|
|
|
199
199
|
var output: VertexOutput;
|
|
200
200
|
output.position = pixelsToClip(pos);
|
|
201
201
|
output.colorValue = colorValues[rowIdx];
|
|
202
|
-
output.alpha = config.opacity * selectionDim(
|
|
203
|
-
${
|
|
202
|
+
output.alpha = config.opacity * entranceAlpha(0u) * selectionDim(
|
|
203
|
+
${connectedActivityWGSL(ACTIVITY_READS, {
|
|
204
204
|
color: 'config.colorMode, config.colorScaleIndex, colorValues[rowIdx]',
|
|
205
205
|
group: 'config.groupIndex'
|
|
206
206
|
})}
|
|
@@ -283,8 +283,8 @@
|
|
|
283
283
|
var output: VertexOutput;
|
|
284
284
|
output.position = pixelsToClip(finalPos);
|
|
285
285
|
output.colorValue = colorValues[rowIdx];
|
|
286
|
-
output.alpha = config.opacity * selectionDim(
|
|
287
|
-
${
|
|
286
|
+
output.alpha = config.opacity * entranceAlpha(0u) * selectionDim(
|
|
287
|
+
${connectedActivityWGSL(ACTIVITY_READS, {
|
|
288
288
|
color: 'config.colorMode, config.colorScaleIndex, colorValues[rowIdx]',
|
|
289
289
|
group: 'config.groupIndex'
|
|
290
290
|
})}
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
DX: 32,
|
|
50
50
|
DY: 36,
|
|
51
51
|
OTHER_COLOR_ON_BAND: 40,
|
|
52
|
-
SPLIT_ALONG_X: 44
|
|
52
|
+
SPLIT_ALONG_X: 44,
|
|
53
|
+
ENTRANCE_AXIS: 48
|
|
53
54
|
};
|
|
54
55
|
|
|
55
56
|
interface Props {
|
|
@@ -67,6 +68,12 @@
|
|
|
67
68
|
share?: SplitProp | null;
|
|
68
69
|
facetData?: Float32Array | null;
|
|
69
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;
|
|
70
77
|
zIndex?: number;
|
|
71
78
|
colorMode?: number;
|
|
72
79
|
colorScaleIndex?: number;
|
|
@@ -79,14 +86,22 @@
|
|
|
79
86
|
markId?: string;
|
|
80
87
|
/**
|
|
81
88
|
* The band axis, when this mark's rows are one per category in category
|
|
82
|
-
* 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.
|
|
83
91
|
*
|
|
84
92
|
* The OTHER axis's channels morph. The band's never do: they carry a
|
|
85
93
|
* category id that the shader resolves through the slot table, and
|
|
86
94
|
* interpolating an identity produces a fraction that resolves to some
|
|
87
|
-
* 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.
|
|
88
97
|
*/
|
|
89
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;
|
|
90
105
|
}
|
|
91
106
|
|
|
92
107
|
let {
|
|
@@ -99,6 +114,7 @@
|
|
|
99
114
|
share = null,
|
|
100
115
|
facetData = null,
|
|
101
116
|
dataVersion,
|
|
117
|
+
landsFor = 0,
|
|
102
118
|
zIndex = 0,
|
|
103
119
|
colorMode = 0,
|
|
104
120
|
colorScaleIndex = 0,
|
|
@@ -108,7 +124,8 @@
|
|
|
108
124
|
dx = 0,
|
|
109
125
|
dy = 0,
|
|
110
126
|
markId = '',
|
|
111
|
-
bandAxis = null
|
|
127
|
+
bandAxis = null,
|
|
128
|
+
grow = null
|
|
112
129
|
}: Props = $props();
|
|
113
130
|
|
|
114
131
|
const splitData = $derived(share?.data ?? null);
|
|
@@ -164,6 +181,10 @@
|
|
|
164
181
|
dy: f32, // Vertical pixel offset
|
|
165
182
|
otherColorOnBand: u32, // 1: an Other row skips its colour activity too
|
|
166
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,
|
|
167
188
|
};
|
|
168
189
|
@group(1) @binding(6) var<uniform> markConstants: MarkConstants;
|
|
169
190
|
|
|
@@ -208,13 +229,19 @@
|
|
|
208
229
|
// Y axis scaling (generated based on scale type)
|
|
209
230
|
{{Y_AXIS_LOGIC}}
|
|
210
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
|
+
|
|
211
237
|
// Apply inset (shrink rect inward on all sides)
|
|
212
|
-
let ix = markConstants.inset * sign(
|
|
213
|
-
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);
|
|
214
240
|
|
|
215
241
|
// Interpolate rectangle corners and apply pixel offsets
|
|
216
|
-
let finalX = mix(
|
|
217
|
-
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);
|
|
218
245
|
|
|
219
246
|
// Convert to normalized device coordinates
|
|
220
247
|
let worldPos = vec2<f32>(finalX, finalY);
|
|
@@ -239,7 +266,7 @@
|
|
|
239
266
|
y: 'y0',
|
|
240
267
|
group: 'markConstants.groupIndex'
|
|
241
268
|
})};
|
|
242
|
-
output.alpha = alpha * selectionDim(activity);
|
|
269
|
+
output.alpha = alpha * selectionDim(activity) * enterAlpha;
|
|
243
270
|
// The unselected part is drawn only on an Other row: every other bar skips
|
|
244
271
|
// its activity reads.
|
|
245
272
|
output.alphaRest = output.alpha;
|
|
@@ -254,7 +281,7 @@
|
|
|
254
281
|
bandFreeActivityY(markConstants.groupIndex),
|
|
255
282
|
markConstants.splitAlongX == 1u
|
|
256
283
|
);
|
|
257
|
-
output.alphaRest = alpha * selectionDim(min(otherActivity, free));
|
|
284
|
+
output.alphaRest = alpha * selectionDim(min(otherActivity, free)) * enterAlpha;
|
|
258
285
|
}
|
|
259
286
|
return output;
|
|
260
287
|
}
|
|
@@ -326,6 +353,18 @@
|
|
|
326
353
|
|
|
327
354
|
// --- DATA WRITING EFFECTS (Independent & Fine-Grained) ---
|
|
328
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
|
+
|
|
329
368
|
// The measure axis's two edges morph, as ONE write per data update, so one
|
|
330
369
|
// update starts one transition. The band's ids go with them: they are how a
|
|
331
370
|
// row set that is not the one being animated gets noticed and snapped.
|
|
@@ -339,7 +378,7 @@
|
|
|
339
378
|
// split and the bar land together. A share that changes alone (a click)
|
|
340
379
|
// starts a transition of its own on that clock.
|
|
341
380
|
const split = splitData ? ([[BINDINGS.SHARE, splitData]] as const) : [];
|
|
342
|
-
const land = splitData && !splitSlides ? [BINDINGS.SHARE] : undefined;
|
|
381
|
+
const land = landsNow() ? 'all' : splitData && !splitSlides ? [BINDINGS.SHARE] : undefined;
|
|
343
382
|
if (bandAxis === 'x') {
|
|
344
383
|
renderer.writeMorphed(
|
|
345
384
|
'x',
|
|
@@ -419,6 +458,7 @@
|
|
|
419
458
|
view.setFloat32(UNIFORM_OFFSETS.DY, dy, LE);
|
|
420
459
|
view.setUint32(UNIFORM_OFFSETS.OTHER_COLOR_ON_BAND, otherColorOnBand ? 1 : 0, LE);
|
|
421
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);
|
|
422
462
|
|
|
423
463
|
renderer.writeUniform(BINDINGS.CONSTANTS, new Uint8Array(buffer));
|
|
424
464
|
}
|