waveform-analysis 0.1.51 → 0.1.52
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 +5 -2
- package/dist/index.cjs +1 -1
- package/dist/index.js +5 -3
- package/dist/types/components/core/useWaveformChartController.d.ts +1 -0
- package/dist/types/components/core/waveformChartTypes.d.ts +1 -0
- package/dist/types/components/interaction/zoomConstraints.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/core/useWaveformChartLifecycle.ts +1 -0
- package/src/components/core/waveformChartTypes.ts +1 -0
- package/src/components/interaction/useWaveformZoom.ts +1 -1
- package/src/components/interaction/zoomConstraints.ts +9 -4
- package/src/components/waveformChartCases/zoomPointConstraints.test.ts +63 -3
- package/src/views/WasmSamplingDemo.vue +7 -0
package/dist/index.js
CHANGED
|
@@ -2062,8 +2062,8 @@ function wr(e, t, n) {
|
|
|
2062
2062
|
function Tr(e, t, n) {
|
|
2063
2063
|
let r = xr(e), i = r[1] - r[0];
|
|
2064
2064
|
if (!Number.isFinite(i) || i <= 0) return 0;
|
|
2065
|
-
let a = Number.isFinite(n.minZoomSpan) && (n.minZoomSpan ?? 0) > 0 ? Math.min(i, n.minZoomSpan) : 0, o = Sr(n.minVisiblePoints), s = wr(t, r, o);
|
|
2066
|
-
return
|
|
2065
|
+
let a = Number.isFinite(n.minZoomSpan) && (n.minZoomSpan ?? 0) > 0 ? Math.min(i, n.minZoomSpan) : 0, o = Sr(n.minVisiblePoints), s = wr(t, r, o), c = Number(n.maxZoomScale), l = Number.isFinite(c) && c >= Rt.MIN_SCALE ? i / c : n.maxZoomScale !== null && a === 0 && o === 0 ? i / Rt.DEFAULT_MAX_SCALE : 0;
|
|
2066
|
+
return Math.max(a, s, l);
|
|
2067
2067
|
}
|
|
2068
2068
|
function Er(e, t, n, r) {
|
|
2069
2069
|
if (r <= 0) return e;
|
|
@@ -2429,7 +2429,7 @@ function Mr(e) {
|
|
|
2429
2429
|
let r = Math.abs(e[1] - e[0]);
|
|
2430
2430
|
if (!Number.isFinite(r) || r <= 0) return Rt.MIN_SCALE;
|
|
2431
2431
|
let i = Tr(e, n, t);
|
|
2432
|
-
return Math.max(Rt.MIN_SCALE, i > 0 ? r / i :
|
|
2432
|
+
return Math.max(Rt.MIN_SCALE, i > 0 ? r / i : Infinity);
|
|
2433
2433
|
}, R = (e, n, r, i) => Or(Dr(e.rescaleX(U(n, [0, r])).domain(), n, i, t), n, r), z = (e) => {
|
|
2434
2434
|
let n = Number(t.minVisiblePoints);
|
|
2435
2435
|
return On(e.seriesList, e.xScale.domain(), Number.isFinite(n) && n > 0 ? Math.ceil(n) + 1 : n);
|
|
@@ -2535,6 +2535,7 @@ function Pr(e) {
|
|
|
2535
2535
|
z,
|
|
2536
2536
|
() => t.minZoomSpan,
|
|
2537
2537
|
() => t.minVisiblePoints,
|
|
2538
|
+
() => t.maxZoomScale,
|
|
2538
2539
|
() => t.initialXDomain,
|
|
2539
2540
|
() => t.initialXDomains,
|
|
2540
2541
|
() => t.xDomainStrategy,
|
|
@@ -5533,6 +5534,7 @@ var po = ["clip-path"], mo = ["data-series-id", "data-series-name"], ho = [
|
|
|
5533
5534
|
},
|
|
5534
5535
|
minZoomSpan: {},
|
|
5535
5536
|
minVisiblePoints: { default: 0 },
|
|
5537
|
+
maxZoomScale: {},
|
|
5536
5538
|
initialXDomain: {},
|
|
5537
5539
|
initialXDomains: {},
|
|
5538
5540
|
xDomainStrategy: { default: () => ({ type: "data" }) },
|
|
@@ -334,6 +334,7 @@ export declare function useWaveformChartController(props: ResolvedWaveformChartP
|
|
|
334
334
|
pannable: boolean;
|
|
335
335
|
minZoomSpan?: number | undefined;
|
|
336
336
|
minVisiblePoints: number;
|
|
337
|
+
maxZoomScale?: number | null | undefined;
|
|
337
338
|
initialXDomains?: Record<string, [number, number]> | undefined;
|
|
338
339
|
xDomainStrategy: import("../..").WaveformXDomainStrategy;
|
|
339
340
|
yDomain?: [number, number] | undefined;
|
|
@@ -14,6 +14,7 @@ export interface WaveformChartProps {
|
|
|
14
14
|
pannable?: boolean;
|
|
15
15
|
minZoomSpan?: number;
|
|
16
16
|
minVisiblePoints?: number;
|
|
17
|
+
maxZoomScale?: number | null;
|
|
17
18
|
initialXDomain?: [number, number];
|
|
18
19
|
initialXDomains?: Record<string, [number, number]>;
|
|
19
20
|
xDomainStrategy?: WaveformXDomainStrategy;
|
|
@@ -9,6 +9,7 @@ export type ZoomSeriesGroup = readonly PointSeriesSource[];
|
|
|
9
9
|
interface ZoomConstraintOptions {
|
|
10
10
|
minZoomSpan?: number;
|
|
11
11
|
minVisiblePoints?: number;
|
|
12
|
+
maxZoomScale?: number | null;
|
|
12
13
|
}
|
|
13
14
|
export declare function resolveMinimumZoomSpan(boundary: [number, number], groups: readonly ZoomSeriesGroup[], options: ZoomConstraintOptions): number;
|
|
14
15
|
export declare function constrainZoomDomain(domain: [number, number], boundary: [number, number], groups: readonly ZoomSeriesGroup[], options: ZoomConstraintOptions): [number, number];
|
package/package.json
CHANGED
|
@@ -213,6 +213,7 @@ export function useWaveformChartLifecycle(context: LifecycleContext) {
|
|
|
213
213
|
isPresentationMode,
|
|
214
214
|
() => props.minZoomSpan,
|
|
215
215
|
() => props.minVisiblePoints,
|
|
216
|
+
() => props.maxZoomScale,
|
|
216
217
|
() => props.initialXDomain,
|
|
217
218
|
() => props.initialXDomains,
|
|
218
219
|
() => props.xDomainStrategy,
|
|
@@ -35,6 +35,7 @@ export interface WaveformChartProps {
|
|
|
35
35
|
pannable?: boolean
|
|
36
36
|
minZoomSpan?: number
|
|
37
37
|
minVisiblePoints?: number
|
|
38
|
+
maxZoomScale?: number | null
|
|
38
39
|
initialXDomain?: [number, number]
|
|
39
40
|
initialXDomains?: Record<string, [number, number]>
|
|
40
41
|
xDomainStrategy?: WaveformXDomainStrategy
|
|
@@ -231,7 +231,7 @@ export function useWaveformZoom(context: ZoomContext) {
|
|
|
231
231
|
const minimumSpan = resolveMinimumZoomSpan(domain, groups, props)
|
|
232
232
|
return Math.max(
|
|
233
233
|
ZOOM_CONSTRAINTS.MIN_SCALE,
|
|
234
|
-
minimumSpan > 0 ? domainSpan / minimumSpan :
|
|
234
|
+
minimumSpan > 0 ? domainSpan / minimumSpan : Number.POSITIVE_INFINITY,
|
|
235
235
|
)
|
|
236
236
|
}
|
|
237
237
|
const constrainTransform = (
|
|
@@ -14,6 +14,7 @@ export type ZoomSeriesGroup = readonly PointSeriesSource[]
|
|
|
14
14
|
interface ZoomConstraintOptions {
|
|
15
15
|
minZoomSpan?: number
|
|
16
16
|
minVisiblePoints?: number
|
|
17
|
+
maxZoomScale?: number | null
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
const xValueCache = new WeakMap<object, Map<string, number[]>>()
|
|
@@ -80,10 +81,14 @@ export function resolveMinimumZoomSpan(
|
|
|
80
81
|
: 0
|
|
81
82
|
const required = resolveRequiredPointCount(options.minVisiblePoints)
|
|
82
83
|
const pointSpan = minimumPointSpan(groups, normalized, required)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
const configuredScale = Number(options.maxZoomScale)
|
|
85
|
+
const scaleSpan =
|
|
86
|
+
Number.isFinite(configuredScale) && configuredScale >= ZOOM_CONSTRAINTS.MIN_SCALE
|
|
87
|
+
? boundarySpan / configuredScale
|
|
88
|
+
: options.maxZoomScale !== null && configuredSpan === 0 && required === 0
|
|
89
|
+
? boundarySpan / ZOOM_CONSTRAINTS.DEFAULT_MAX_SCALE
|
|
90
|
+
: 0
|
|
91
|
+
return Math.max(configuredSpan, pointSpan, scaleSpan)
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
function expandToMinimumPoints(
|
|
@@ -65,10 +65,10 @@ function dispatchBox(
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
describe('WaveformChart point-aware zoom constraints', () => {
|
|
68
|
-
it('
|
|
68
|
+
it('zooms to two distinct X values when the scale limit is disabled', async () => {
|
|
69
69
|
const wrapper = await mountSizedChart(
|
|
70
70
|
{ kind: 'points', points: regularPoints },
|
|
71
|
-
{ minVisiblePoints: 2 },
|
|
71
|
+
{ minVisiblePoints: 2, maxZoomScale: null },
|
|
72
72
|
)
|
|
73
73
|
const { overlay, width, height } = prepareOverlay(
|
|
74
74
|
wrapper,
|
|
@@ -151,7 +151,7 @@ describe('WaveformChart point-aware zoom constraints', () => {
|
|
|
151
151
|
expect(visibleXCount(constrainedDomain)).toBe(2)
|
|
152
152
|
})
|
|
153
153
|
|
|
154
|
-
it('retains the default
|
|
154
|
+
it('retains the backwards-compatible default maximum zoom scale', async () => {
|
|
155
155
|
const wrapper = await mountSizedChart({ kind: 'points', points: regularPoints })
|
|
156
156
|
const { overlay, width, height } = prepareOverlay(
|
|
157
157
|
wrapper,
|
|
@@ -163,6 +163,66 @@ describe('WaveformChart point-aware zoom constraints', () => {
|
|
|
163
163
|
expect(domain[1] - domain[0]).toBeCloseTo(1_199 / 40)
|
|
164
164
|
})
|
|
165
165
|
|
|
166
|
+
it('honors an explicit maximum zoom scale', async () => {
|
|
167
|
+
const wrapper = await mountSizedChart(
|
|
168
|
+
{ kind: 'points', points: regularPoints },
|
|
169
|
+
{ maxZoomScale: 20 },
|
|
170
|
+
)
|
|
171
|
+
const { overlay, width, height } = prepareOverlay(
|
|
172
|
+
wrapper,
|
|
173
|
+
'.waveform-chart__overlay--independent',
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
await dispatchWheel(overlay, width, height, -4_000)
|
|
177
|
+
const domain = wrapper.emitted('zoom-change')?.at(-1)?.[0] as [number, number]
|
|
178
|
+
expect(domain[1] - domain[0]).toBeCloseTo(1_199 / 20)
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
it('disables the compatibility scale limit when configured with null', async () => {
|
|
182
|
+
const wrapper = await mountSizedChart(
|
|
183
|
+
{ kind: 'points', points: regularPoints },
|
|
184
|
+
{ maxZoomScale: null },
|
|
185
|
+
)
|
|
186
|
+
const { overlay, width, height } = prepareOverlay(
|
|
187
|
+
wrapper,
|
|
188
|
+
'.waveform-chart__overlay--independent',
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
await dispatchWheel(overlay, width, height, -4_000)
|
|
192
|
+
const domain = wrapper.emitted('zoom-change')?.at(-1)?.[0] as [number, number]
|
|
193
|
+
expect(domain[1] - domain[0]).toBeLessThan(1_199 / 40)
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
it('falls back to the compatibility limit for an invalid maximum scale', async () => {
|
|
197
|
+
const wrapper = await mountSizedChart(
|
|
198
|
+
{ kind: 'points', points: regularPoints },
|
|
199
|
+
{ maxZoomScale: 0 },
|
|
200
|
+
)
|
|
201
|
+
const { overlay, width, height } = prepareOverlay(
|
|
202
|
+
wrapper,
|
|
203
|
+
'.waveform-chart__overlay--independent',
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
await dispatchWheel(overlay, width, height, -4_000)
|
|
207
|
+
const domain = wrapper.emitted('zoom-change')?.at(-1)?.[0] as [number, number]
|
|
208
|
+
expect(domain[1] - domain[0]).toBeCloseTo(1_199 / 40)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
it('uses the strictest configured zoom constraint', async () => {
|
|
212
|
+
const wrapper = await mountSizedChart(
|
|
213
|
+
{ kind: 'points', points: regularPoints },
|
|
214
|
+
{ minZoomSpan: 50, minVisiblePoints: 2, maxZoomScale: 40 },
|
|
215
|
+
)
|
|
216
|
+
const { overlay, width, height } = prepareOverlay(
|
|
217
|
+
wrapper,
|
|
218
|
+
'.waveform-chart__overlay--independent',
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
await dispatchWheel(overlay, width, height, -4_000)
|
|
222
|
+
const domain = wrapper.emitted('zoom-change')?.at(-1)?.[0] as [number, number]
|
|
223
|
+
expect(domain[1] - domain[0]).toBeCloseTo(50)
|
|
224
|
+
})
|
|
225
|
+
|
|
166
226
|
it('retains two endpoint samples while replacing an independent data window', async () => {
|
|
167
227
|
const sourcePoints = Array.from({ length: 1_000 }, (_, index) => ({
|
|
168
228
|
x: -5 + (index * 10) / 999,
|
|
@@ -68,6 +68,7 @@ const mode = ref<WaveformSamplingMode>('auto')
|
|
|
68
68
|
const strategy = ref<WaveformSamplingStrategy>('peak')
|
|
69
69
|
const autoThreshold = ref(1_000)
|
|
70
70
|
const maxPointsPerPixel = ref(3)
|
|
71
|
+
const minVisiblePoints = ref(2)
|
|
71
72
|
const diagnostics = reactive<Record<string, WaveformSamplingDiagnostics | undefined>>({})
|
|
72
73
|
|
|
73
74
|
const rendering = computed<WaveformRenderingOptions>(() => ({
|
|
@@ -135,6 +136,10 @@ function pointCount(value: number | undefined) {
|
|
|
135
136
|
size="small"
|
|
136
137
|
/>
|
|
137
138
|
</label>
|
|
139
|
+
<label>
|
|
140
|
+
<span>最少可见点</span>
|
|
141
|
+
<InputNumber v-model:value="minVisiblePoints" :min="2" :max="1000" :step="1" size="small" />
|
|
142
|
+
</label>
|
|
138
143
|
</section>
|
|
139
144
|
|
|
140
145
|
<section class="sampling-demo__workspace">
|
|
@@ -144,6 +149,8 @@ function pointCount(value: number | undefined) {
|
|
|
144
149
|
:rendering="rendering"
|
|
145
150
|
:grid="{ rowCount: 1, columnCount: 1, showPagination: false }"
|
|
146
151
|
:legend="{ position: 'top-right', orientation: 'vertical' }"
|
|
152
|
+
:max-zoom-scale="null"
|
|
153
|
+
:min-visible-points="minVisiblePoints"
|
|
147
154
|
:title="{ visible: true, text: '多系列采样与缓存诊断', align: 'left' }"
|
|
148
155
|
x-label="时间(s)"
|
|
149
156
|
time-unit="s"
|