({
duration,
boundaries,
cap,
}: TransitionSampleOptions)
| 262 | * subset and `dropped` reports how many sample times were omitted. |
| 263 | */ |
| 264 | export function buildTransitionSampleTimes({ |
| 265 | duration, |
| 266 | boundaries, |
| 267 | cap, |
| 268 | }: TransitionSampleOptions): TransitionSamples { |
| 269 | if (!Number.isFinite(duration) || duration <= 0) return { times: [], dropped: 0 }; |
| 270 | const inRange = uniqueSortedTimes( |
| 271 | boundaries.filter((time) => Number.isFinite(time) && time >= 0 && time <= duration), |
| 272 | ); |
| 273 | const withMidpoints = [...inRange]; |
| 274 | for (let i = 0; i < inRange.length - 1; i++) { |
| 275 | const current = inRange[i]; |
| 276 | const next = inRange[i + 1]; |
| 277 | if (current === undefined || next === undefined) continue; |
| 278 | withMidpoints.push(roundTime((current + next) / 2)); |
| 279 | } |
| 280 | const merged = uniqueSortedTimes(withMidpoints); |
| 281 | if (cap === undefined || merged.length <= Math.max(2, cap)) { |
| 282 | return { times: merged, dropped: 0 }; |
| 283 | } |
| 284 | const limit = Math.max(2, cap); |
| 285 | const strided: number[] = []; |
| 286 | for (let i = 0; i < limit; i++) { |
| 287 | const pick = merged[Math.floor((i * (merged.length - 1)) / (limit - 1))]; |
| 288 | if (pick !== undefined) strided.push(pick); |
| 289 | } |
| 290 | const times = uniqueSortedTimes(strided); |
| 291 | return { times, dropped: merged.length - times.length }; |
| 292 | } |
| 293 | |
| 294 | /** Merge sample-time lists into one deduplicated ascending list. */ |
| 295 | export function mergeSampleTimes(...lists: number[][]): number[] { |
no test coverage detected