feat: 优化波形渲染性能与交互
All checks were successful
Package component / package (push) Successful in 5m56s

This commit is contained in:
李启源
2026-07-22 16:36:48 +08:00
parent 356f55c9fd
commit 5b0ba7413e
35 changed files with 8208 additions and 246 deletions

View File

@@ -1,6 +1,6 @@
import { describe, expect, it, vi } from 'vitest'
import { normalizeWaveformData } from './data'
import { normalizeWaveformData, normalizeWaveformSeries } from './data'
describe('waveform data normalization', () => {
it('builds sample points in one pass while preserving source indexes', () => {
@@ -55,4 +55,51 @@ describe('waveform data normalization', () => {
{ x: 2, y: 20 },
])
})
it('preserves every valid point in large data sets', () => {
const points = Array.from({ length: 10_001 }, (_, index) => ({
x: index,
y: index === 5_555 ? 1 : 0,
...(index === 5_555 ? { error: 10_000 } : {}),
}))
const result = normalizeWaveformData({ kind: 'points', points })
expect(result).toHaveLength(points.length)
expect(result[5_555]).toEqual({ x: 5_555, y: 1, error: 10_000 })
})
it('defaults and normalizes per-series line styles', () => {
const data = {
kind: 'series' as const,
series: [
{ id: 'solid', name: 'Solid', data: { kind: 'points' as const, points: [{ x: 0, y: 1 }] } },
{
id: 'dashed',
name: 'Dashed',
lineStyle: 'dashed' as const,
data: { kind: 'points' as const, points: [{ x: 0, y: 1 }] },
},
{
id: 'dash-dot',
name: 'Dash dot',
lineStyle: 'dash-dot' as const,
data: { kind: 'points' as const, points: [{ x: 0, y: 1 }] },
},
{
id: 'invalid',
name: 'Invalid',
lineStyle: 'zigzag' as never,
data: { kind: 'points' as const, points: [{ x: 0, y: 1 }] },
},
],
}
expect(normalizeWaveformSeries(data).map((series) => series.lineStyle)).toEqual([
'solid',
'dashed',
'dash-dot',
'solid',
])
})
})

View File

@@ -2,11 +2,17 @@ import type {
SingleWaveformData,
WaveformData,
WaveformPoint,
WaveformLineStyle,
NormalizedWaveformSeries,
} from '../types'
import { ERROR_BAR_DEFAULTS } from '../components/core/constants'
const DEFAULT_ERROR_BAR_WIDTH = 1.5
const DEFAULT_ERROR_BAR_CAP_WIDTH = 8
const DEFAULT_ERROR_BAR_WIDTH = ERROR_BAR_DEFAULTS.WIDTH
const DEFAULT_ERROR_BAR_CAP_WIDTH = ERROR_BAR_DEFAULTS.CAP_WIDTH
function normalizeLineStyle(value: unknown): WaveformLineStyle {
return value === 'dashed' || value === 'dash-dot' ? value : 'solid'
}
function normalizeError(value: number | undefined): number | undefined {
return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined
@@ -52,6 +58,7 @@ export function normalizeWaveformData(data: SingleWaveformData): WaveformPoint[]
if (!Number.isFinite(value)) continue
points.push({ x: startTime + index / data.sampleRate, y: value })
}
return points
}
@@ -66,6 +73,7 @@ export function normalizeWaveformData(data: SingleWaveformData): WaveformPoint[]
points.push(normalized)
}
if (!sorted) points.sort((left, right) => left.x - right.x)
return points
}
@@ -83,6 +91,7 @@ export function normalizeWaveformSeries(data: WaveformData): NormalizedWaveformS
id: 'series-0',
name: '',
lineType: 'linear',
lineStyle: 'solid',
pointType: 'none',
errorBar: {
visible: false,
@@ -111,6 +120,7 @@ export function normalizeWaveformSeries(data: WaveformData): NormalizedWaveformS
usedIds.add(uniqueId)
const requestedLineType = series.lineType ?? 'linear'
const lineStyle = normalizeLineStyle((series as { lineStyle?: unknown }).lineStyle)
const requestedPointType = series.pointType ?? 'none'
const errorBarVisible = series.errorBar?.visible === true
const lineType =
@@ -127,6 +137,7 @@ export function normalizeWaveformSeries(data: WaveformData): NormalizedWaveformS
unit: series.unit,
color: series.color,
lineType,
lineStyle,
pointType: requestedPointType,
errorBar: {
visible: errorBarVisible,