feat(chart): improve adaptive waveform layout
This commit is contained in:
28
src/utils/domain.test.ts
Normal file
28
src/utils/domain.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
|
||||
import { buildMinorTicks } from './domain'
|
||||
|
||||
describe('buildMinorTicks', () => {
|
||||
it('preserves the existing behavior when no domain is provided', () => {
|
||||
expect(buildMinorTicks([0, 10, 20], 5)).toEqual([2, 4, 6, 8, 12, 14, 16, 18])
|
||||
})
|
||||
|
||||
it('fills the partial interval after the final major tick', () => {
|
||||
const majorTicks = Array.from({ length: 13 }, (_, index) => -8000 + index * 1000)
|
||||
|
||||
expect(buildMinorTicks(majorTicks, 5, [-8000, 4990.3]).slice(-4)).toEqual([
|
||||
4200, 4400, 4600, 4800,
|
||||
])
|
||||
})
|
||||
|
||||
it('fills both edge intervals and excludes the domain endpoints', () => {
|
||||
const ticks = buildMinorTicks([-7000, -6000, -5000], 5, [-7950, -4100])
|
||||
|
||||
expect(ticks).toEqual([
|
||||
-7800, -7600, -7400, -7200, -6800, -6600, -6400, -6200, -5800, -5600, -5400,
|
||||
-5200, -4800, -4600, -4400, -4200,
|
||||
])
|
||||
expect(ticks).not.toContain(-7950)
|
||||
expect(ticks).not.toContain(-4100)
|
||||
})
|
||||
})
|
||||
@@ -17,13 +17,34 @@ export function paddedDomain(values: number[]): [number, number] {
|
||||
* 在主刻度之间生成次要刻度
|
||||
* @param values 主刻度值数组
|
||||
* @param subdivisions 细分数量,默认 5
|
||||
* @param domain 可选的可见域,用于补齐首尾不完整主刻度区间内的次要刻度
|
||||
* @returns 次要刻度值数组
|
||||
*/
|
||||
export function buildMinorTicks(values: number[], subdivisions = 5): number[] {
|
||||
return values.flatMap((value, index) => {
|
||||
const nextValue = values[index + 1]
|
||||
export function buildMinorTicks(
|
||||
values: number[],
|
||||
subdivisions = 5,
|
||||
domain?: readonly [number, number],
|
||||
): number[] {
|
||||
let intervalBoundaries = values
|
||||
|
||||
if (domain && values.length >= 2) {
|
||||
const first = values[0]
|
||||
const second = values[1]
|
||||
const last = values[values.length - 1]
|
||||
const previous = values[values.length - 2]
|
||||
intervalBoundaries = [first - (second - first), ...values, last + (last - previous)]
|
||||
}
|
||||
|
||||
const minorTicks = intervalBoundaries.flatMap((value, index) => {
|
||||
const nextValue = intervalBoundaries[index + 1]
|
||||
if (nextValue === undefined) return []
|
||||
const step = (nextValue - value) / subdivisions
|
||||
return Array.from({ length: subdivisions - 1 }, (_, minorIndex) => value + step * (minorIndex + 1))
|
||||
})
|
||||
|
||||
if (!domain) return minorTicks
|
||||
|
||||
const domainMinimum = Math.min(...domain)
|
||||
const domainMaximum = Math.max(...domain)
|
||||
return minorTicks.filter((tick) => tick > domainMinimum && tick < domainMaximum)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user