first commit
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
李启源
2026-07-20 10:21:30 +08:00
commit ea832229da
75 changed files with 16864 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
import { line, scaleLinear, zoomIdentity, type ZoomTransform } from 'd3'
import { selectRenderablePoints, type ResolvedWaveformRenderingOptions } from '../../core'
import type { WaveformDisplayMode, WaveformPoint } from '../../types'
import { buildMinorTicks, formatEndpointTime } from '../../utils'
import {
getBottomRowCellIndexes,
type GridCellGeometry,
type NormalizedWaveformGridOptions,
} from './grid'
import type { DisplaySeries, TrackLayout } from './types'
interface SeriesGridCell extends GridCellGeometry {
series?: DisplaySeries
}
export interface BuildTrackLayoutsOptions {
cells: SeriesGridCell[]
grid: NormalizedWaveformGridOptions
displayMode: WaveformDisplayMode
independentTransforms: ZoomTransform[]
sharedZoomDomain: [number, number]
timeUnit: 's' | 'ms'
rendering: ResolvedWaveformRenderingOptions
hideSecondaryLabels: boolean
yAxisLabelX: number
}
export function buildTrackLayouts(options: BuildTrackLayoutsOptions): TrackLayout[] {
const visibleCells = options.cells.map((cell) => ({ ...cell, hasSeries: Boolean(cell.series) }))
const bottomCells = getBottomRowCellIndexes(visibleCells, options.grid.columnCount)
return visibleCells.flatMap((cell, index) => {
const series = cell.series
if (!series) return []
const baseXScale =
options.displayMode === 'independent'
? scaleLinear(series.xDomain, [0, cell.width])
: scaleLinear(options.sharedZoomDomain, [0, cell.width])
const transform =
options.displayMode === 'independent'
? (options.independentTransforms[index] ?? zoomIdentity)
: zoomIdentity
const xScale = transform.rescaleX(baseXScale)
const yScale = scaleLinear(series.yDomain, [cell.plotHeight, 0]).nice()
const xMajorTicks = xScale.ticks(Math.max(2, Math.floor(cell.width / 100)))
const yMajorTicks = yScale.ticks(Math.max(2, Math.floor(cell.plotHeight / 55)))
const yAxisTickValues =
options.displayMode === 'compact' && cell.row < options.grid.rowCount - 1
? yMajorTicks.slice(1)
: yMajorTicks
const domain = xScale.domain() as [number, number]
const endpointLabels = {
start: formatEndpointTime(domain[0], domain, options.timeUnit),
end: formatEndpointTime(domain[1], domain, options.timeUnit),
}
const leftClearance = endpointLabels.start.length * 7 + 10
const rightClearance = endpointLabels.end.length * 7 + 10
const xAxisTickValues = xMajorTicks.filter((tick) => {
const position = xScale(tick)
return position > leftClearance && position < cell.width - rightClearance
})
const renderPoints = selectRenderablePoints(
series.points,
domain,
cell.width,
options.rendering,
)
return {
index,
series,
column: cell.column,
showYAxisLabel: !options.hideSecondaryLabels || cell.column === 0,
yAxisLabelX: options.yAxisLabelX,
left: cell.left,
top: cell.top,
width: cell.width,
height: cell.plotHeight,
xScale,
yScale,
xMajorTicks,
xMinorTicks: buildMinorTicks(xMajorTicks),
yMajorTicks,
yMinorTicks: buildMinorTicks(yMajorTicks),
yAxisTickValues,
xAxisTickValues,
endpointLabels,
path: line<WaveformPoint>()
.x((point) => xScale(point.x))
.y((point) => yScale(point.y))(renderPoints),
showXAxis: options.displayMode === 'independent' || bottomCells.has(cell.slotIndex),
}
})
}