Files
gui-video-clipper/src/lib/timeline/interactions.ts

56 lines
1.5 KiB
TypeScript
Raw Normal View History

import { type TimelineState, xToTime } from './renderer';
export type { TimelineState };
const MIN_VISIBLE_RANGE = 0.1;
const MIN_ZOOM = 1;
export function clampZoom(zoom: number, duration: number): number {
const maxZoom = duration / MIN_VISIBLE_RANGE;
return Math.max(MIN_ZOOM, Math.min(zoom, maxZoom));
}
export function computeZoom(
state: TimelineState,
anchorTime: number,
factor: number,
duration: number
): { visibleStart: number; visibleEnd: number; zoom: number } {
const currentRange = state.visibleEnd - state.visibleStart;
if (currentRange <= 0) {
return {
visibleStart: state.visibleStart,
visibleEnd: state.visibleEnd,
zoom: state.zoom,
};
}
const newRange = currentRange / factor;
const clampedRange = Math.max(MIN_VISIBLE_RANGE, Math.min(newRange, duration));
const anchorRatio = (anchorTime - state.visibleStart) / currentRange;
let newStart = anchorTime - anchorRatio * clampedRange;
let newEnd = newStart + clampedRange;
if (newStart < 0) {
newStart = 0;
newEnd = clampedRange;
}
if (newEnd > duration) {
newEnd = duration;
newStart = Math.max(0, newEnd - clampedRange);
}
const newZoom = clampZoom(duration / clampedRange, duration);
return { visibleStart: newStart, visibleEnd: newEnd, zoom: newZoom };
}
export function handleClick(
x: number,
state: TimelineState,
duration: number
): number {
const time = xToTime(x, state);
return Math.max(0, Math.min(time, duration));
}