优化,添加滚动记忆

This commit is contained in:
truewhile
2026-09-15 00:00:35 +08:00
parent 60f05129c9
commit a563ee11d6
15 changed files with 572 additions and 26 deletions
+22
View File
@@ -0,0 +1,22 @@
import {
formatPlaybackRate,
normalizePlaybackRate,
stepPlaybackRate,
} from './playbackRate.ts'
function check(name: string, condition: boolean) {
if (!condition) throw new Error(`playbackRate: ${name}`)
}
check('invalid value falls back to 1x', normalizePlaybackRate(undefined) === 1)
check('value snaps to nearest selectable rate', normalizePlaybackRate(1.2) === 1.25)
check('value below range clamps to the minimum', normalizePlaybackRate(0.1) === 0.5)
check('value above range clamps to the maximum', normalizePlaybackRate(9) === 3)
check('up steps to the next rate', stepPlaybackRate(1, 1) === 1.25)
check('down steps to the previous rate', stepPlaybackRate(1, -1) === 0.75)
check('up stops at the maximum', stepPlaybackRate(3, 1) === 3)
check('down stops at the minimum', stepPlaybackRate(0.5, -1) === 0.5)
check('integer formatting', formatPlaybackRate(1) === '1x')
check('decimal formatting', formatPlaybackRate(1.25) === '1.25x')
console.log('playbackRate.test.ts ok')
+31
View File
@@ -0,0 +1,31 @@
export const PLAYBACK_RATE_OPTIONS = [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2, 2.5, 3] as const
export const MIN_PLAYBACK_RATE = PLAYBACK_RATE_OPTIONS[0]
export const MAX_PLAYBACK_RATE = PLAYBACK_RATE_OPTIONS[PLAYBACK_RATE_OPTIONS.length - 1]
export function normalizePlaybackRate(value: unknown): number {
const parsed = Number(value)
if (!Number.isFinite(parsed)) return 1
let closest: number = PLAYBACK_RATE_OPTIONS[0]
let closestDistance = Number.POSITIVE_INFINITY
for (const option of PLAYBACK_RATE_OPTIONS) {
const distance = Math.abs(option - parsed)
if (distance < closestDistance) {
closest = option
closestDistance = distance
}
}
return closest
}
export function stepPlaybackRate(current: unknown, direction: 1 | -1): number {
const normalized = normalizePlaybackRate(current)
const index = PLAYBACK_RATE_OPTIONS.indexOf(normalized as (typeof PLAYBACK_RATE_OPTIONS)[number])
const next = Math.min(PLAYBACK_RATE_OPTIONS.length - 1, Math.max(0, index + direction))
return PLAYBACK_RATE_OPTIONS[next]
}
export function formatPlaybackRate(rate: unknown): string {
const normalized = normalizePlaybackRate(rate)
return `${Number.isInteger(normalized) ? normalized.toFixed(0) : String(normalized)}x`
}