feat(chart): add series styling and visibility controls
This commit is contained in:
@@ -55,6 +55,34 @@ describe('waveform annotation markup', () => {
|
||||
).toBeNull()
|
||||
})
|
||||
|
||||
it('interpolates start, middle, and end step lines at their visual transitions', () => {
|
||||
const points = [
|
||||
{ x: 0, y: 2 },
|
||||
{ x: 2, y: 10 },
|
||||
]
|
||||
|
||||
expect(interpolateAnnotationPoint(points, 0.5, 'step-start')).toEqual({ x: 0.5, y: 10 })
|
||||
expect(interpolateAnnotationPoint(points, 0.5, 'step-middle')).toEqual({ x: 0.5, y: 2 })
|
||||
expect(interpolateAnnotationPoint(points, 1, 'step-middle')).toEqual({ x: 1, y: 10 })
|
||||
expect(interpolateAnnotationPoint(points, 1.5, 'step-middle')).toEqual({ x: 1.5, y: 10 })
|
||||
expect(interpolateAnnotationPoint(points, 1, 'step-end')).toEqual({ x: 1, y: 2 })
|
||||
expect(interpolateAnnotationPoint(points, 1, 'step-after')).toEqual({ x: 1, y: 2 })
|
||||
expect(interpolateAnnotationPoint(points, 2, 'step-start')).toEqual({ x: 2, y: 10 })
|
||||
expect(interpolateAnnotationPoint(points, 2, 'step-after')).toEqual({ x: 2, y: 10 })
|
||||
expect(interpolateAnnotationPoint(points, 1, 'none')).toBeNull()
|
||||
expect(interpolateAnnotationPoint(points, 2, 'none')).toEqual({ x: 2, y: 10 })
|
||||
})
|
||||
|
||||
it('omits interpolated candidates for point-only series between samples', () => {
|
||||
const pointOnly = createTrack(0, 'points', 0, [
|
||||
{ x: 0, y: 2 },
|
||||
{ x: 2, y: 10 },
|
||||
])
|
||||
pointOnly.series.lineType = 'none'
|
||||
|
||||
expect(findAnnotationSeriesCandidates([pointOnly], 1, 100, 50)).toEqual([])
|
||||
})
|
||||
|
||||
it('sorts line candidates by screen distance and keeps series metadata', () => {
|
||||
const first = createTrack(0, 'first', 0, [
|
||||
{ x: 0, y: 0 },
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { bisector } from 'd3'
|
||||
|
||||
import type { WaveformAnnotation, WaveformAnnotationStyle } from '../../types'
|
||||
import type { WaveformAnnotation, WaveformAnnotationStyle, WaveformLineType } from '../../types'
|
||||
import type {
|
||||
AnnotationBoxLayout,
|
||||
AnnotationHit,
|
||||
@@ -46,6 +46,7 @@ const pointBisector = bisector((point: { x: number }) => point.x)
|
||||
export function interpolateAnnotationPoint(
|
||||
points: Array<{ x: number; y: number }>,
|
||||
xValue: number,
|
||||
lineType: WaveformLineType = 'linear',
|
||||
): { x: number; y: number } | null {
|
||||
if (!points.length || !Number.isFinite(xValue)) return null
|
||||
const first = points[0]
|
||||
@@ -56,8 +57,16 @@ export function interpolateAnnotationPoint(
|
||||
const rightIndex = pointBisector.left(points, xValue)
|
||||
const right = points[Math.min(rightIndex, points.length - 1)]
|
||||
if (right.x === xValue || rightIndex === 0) return { x: xValue, y: right.y }
|
||||
if (lineType === 'none') return null
|
||||
|
||||
const left = points[rightIndex - 1]
|
||||
if (lineType === 'step-start') return { x: xValue, y: right.y }
|
||||
if (lineType === 'step-middle') {
|
||||
return { x: xValue, y: xValue < (left.x + right.x) / 2 ? left.y : right.y }
|
||||
}
|
||||
if (lineType === 'step-end' || lineType === 'step-after') {
|
||||
return { x: xValue, y: left.y }
|
||||
}
|
||||
const xSpan = right.x - left.x
|
||||
if (xSpan === 0) return { x: xValue, y: right.y }
|
||||
const ratio = (xValue - left.x) / xSpan
|
||||
@@ -72,7 +81,7 @@ export function findAnnotationSeriesCandidates(
|
||||
): AnnotationSeriesCandidate[] {
|
||||
return tracks
|
||||
.flatMap((track): AnnotationSeriesCandidate[] => {
|
||||
const point = interpolateAnnotationPoint(track.series.points, xValue)
|
||||
const point = interpolateAnnotationPoint(track.series.points, xValue, track.series.lineType)
|
||||
if (!point) return []
|
||||
const screenX = track.xScale(point.x)
|
||||
const screenY = track.top + track.yScale(point.y)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ScaleLinear } from 'd3'
|
||||
|
||||
import type { WaveformAnnotation, WaveformPoint } from '../../types'
|
||||
import type { WaveformAnnotation, WaveformLineType, WaveformPoint } from '../../types'
|
||||
|
||||
export interface AnnotationTrackLayout {
|
||||
index: number
|
||||
@@ -9,6 +9,7 @@ export interface AnnotationTrackLayout {
|
||||
name?: string
|
||||
color?: string
|
||||
unit?: string
|
||||
lineType?: WaveformLineType
|
||||
points: WaveformPoint[]
|
||||
}
|
||||
left?: number
|
||||
|
||||
Reference in New Issue
Block a user