feat(坐标轴): 支持显示纵轴单位
All checks were successful
Package component / package (push) Successful in 4m18s

This commit is contained in:
李启源
2026-08-18 10:06:36 +08:00
parent 5c71c28429
commit 233b9b0aa2
10 changed files with 78 additions and 12 deletions

View File

@@ -103,6 +103,7 @@ export function axisTextMetrics(
domain: [number, number],
nice = true,
tickValues?: number[],
unit?: string,
): { tickTextWidth: number } {
const scale = scaleLinear(domain, [1, 0])
if (nice) scale.nice()
@@ -112,7 +113,7 @@ export function axisTextMetrics(
const maximumTickCharacters = Math.max(
1,
...values.map(
(value) => formatScientificAxisLabel(value, { axisMin, axisMax, topTickValue }).length,
(value) => formatScientificAxisLabel(value, { axisMin, axisMax, topTickValue, unit }).length,
),
)
return {
@@ -122,7 +123,8 @@ export function axisTextMetrics(
export function measureYAxisGroupClearance(group: YAxisSeriesGroup): number {
return (
axisTextMetrics(group.domain, !group.fixed).tickTextWidth +
axisTextMetrics(group.domain, !group.fixed, undefined, group.seriesList[0]?.unit)
.tickTextWidth +
Y_AXIS_TICK_PADDING +
Y_AXIS_LABEL_GAP +
Y_AXIS_LABEL_BAND_WIDTH +
@@ -132,7 +134,8 @@ export function measureYAxisGroupClearance(group: YAxisSeriesGroup): number {
function measureYAxisGroupTickClearance(group: YAxisSeriesGroup): number {
return (
axisTextMetrics(group.domain, !group.fixed).tickTextWidth +
axisTextMetrics(group.domain, !group.fixed, undefined, group.seriesList[0]?.unit)
.tickTextWidth +
Y_AXIS_TICK_PADDING +
Y_AXIS_OUTER_PADDING
)

View File

@@ -135,7 +135,12 @@ export function buildTrackLayouts(options: BuildTrackLayoutsOptions): TrackLayou
const tickValues = Array.from(
new Set([axisStart, ...visibleMajorTicks, ...(showAxisEnd ? [axisEnd] : [])]),
)
const { tickTextWidth } = axisTextMetrics(group.domain, !group.fixed, tickValues)
const { tickTextWidth } = axisTextMetrics(
group.domain,
!group.fixed,
tickValues,
group.seriesList[0]?.unit,
)
const clearance =
tickTextWidth +
Y_AXIS_TICK_PADDING +

View File

@@ -112,7 +112,11 @@ export function useWaveformLayout(context: LayoutContext) {
.flatMap((track) =>
resolveYAxisSeriesGroups(track, props.overlayMode, props.yDomain, props.yDomains),
)
.map((group) => axisTextMetrics(group.domain, !group.fixed).tickTextWidth)
.map(
(group) =>
axisTextMetrics(group.domain, !group.fixed, undefined, group.seriesList[0]?.unit)
.tickTextWidth,
)
const tickTextWidth = Math.max(Y_AXIS_CHARACTER_WIDTH, ...axisText)
const tickClearance = tickTextWidth + Y_AXIS_TICK_PADDING + Y_AXIS_OUTER_PADDING
const labelCenterX = -(

View File

@@ -44,9 +44,10 @@ function renderAxes() {
if (!element) return
const [axisMin, axisMax] = axis.scale.domain()
const topTickValue = Math.max(...axis.tickValues)
const unit = axis.seriesList[0]?.unit
const yAxis = (axis.side === 'left' ? axisLeft(axis.scale) : axisRight(axis.scale))
.tickFormat((value) =>
formatScientificAxisLabel(Number(value), { axisMin, axisMax, topTickValue }),
formatScientificAxisLabel(Number(value), { axisMin, axisMax, topTickValue, unit }),
)
.tickSize(-4)
.tickPadding(7)

View File

@@ -158,6 +158,12 @@ describe('WaveformChart', () => {
expect(paths[0].attributes('data-series-name')).toBe('BT2_2M')
const yAxisLabels = wrapper.findAll('.waveform-chart__y-axis-label')
expect(yAxisLabels.map((label) => label.text())).toEqual(['BT2_2M', 'BT1_2M'])
expect(
wrapper
.findAll('.waveform-chart__axis--y .tick text')
.map((label) => label.text())
.some((label) => label.includes('(T)')),
).toBe(true)
expect(yAxisLabels.map((label) => label.attributes('fill'))).toEqual(['#0960bd', '#ff7f0e'])
const labelX = Number(
yAxisLabels[0].attributes('transform')?.match(/^translate\(([-\d.]+),/)?.[1],

View File

@@ -15,6 +15,7 @@ describe('WaveformChart', () => {
{
trackId: 'shared-frame',
name: '普通量程',
unit: 'V',
data: {
kind: 'points',
points: [
@@ -26,6 +27,7 @@ describe('WaveformChart', () => {
{
trackId: 'shared-frame',
name: '大量程',
unit: 'A',
data: {
kind: 'points',
points: [
@@ -37,6 +39,7 @@ describe('WaveformChart', () => {
{
trackId: 'shared-frame',
name: '小量程',
unit: 'T',
data: {
kind: 'points',
points: [
@@ -57,7 +60,11 @@ describe('WaveformChart', () => {
.map((label) => label.text())
.filter((label) => label.startsWith('E')),
),
).toEqual([[], [expect.stringMatching(/^E\+03 /)], [expect.stringMatching(/^E-04 /)]])
).toEqual([
[],
[expect.stringMatching(/^E\+03 \(A\) /)],
[expect.stringMatching(/^E-04 \(T\) /)],
])
})
it('reprojects annotations with the Y axis assigned to their series', async () => {