clipper/frontend/src/helpers/zoom.ts

105 lines
2.1 KiB
TypeScript

import { Frames } from '../App';
export function zoomViewportIn(
viewport: Frames,
numFrames: number,
selection: Frames,
position: number,
factor: number
): Frames {
if (!canZoomViewportIn(viewport, selection, factor)) {
return viewport;
}
return zoom(
Math.round((viewport.end - viewport.start) / factor),
viewport,
numFrames,
selection,
position
);
}
export function zoomViewportOut(
viewport: Frames,
numFrames: number,
selection: Frames,
position: number,
factor: number
): Frames {
if (!canZoomViewportOut(viewport, numFrames)) {
return viewport;
}
return zoom(
Math.round((viewport.end - viewport.start) * factor),
viewport,
numFrames,
selection,
position
);
}
function zoom(
newWidth: number,
viewport: Frames,
numFrames: number,
selection: Frames,
position: number
): Frames {
let newStart;
if (selection.start != selection.end) {
const selectionWidth = selection.end - selection.start;
// disallow zooming beyond the selection:
if (newWidth < selectionWidth) {
return viewport;
}
const selectionMidpoint = selection.end - selectionWidth / 2;
newStart = selectionMidpoint - Math.round(newWidth / 2);
} else {
newStart = position - newWidth / 2;
}
if (newStart < 0) {
newStart = 0;
}
let newEnd = newStart + newWidth;
if (newEnd > numFrames) {
newEnd = numFrames;
newStart = Math.max(0, newEnd - newWidth);
}
return { start: newStart, end: newEnd };
}
export function canZoomViewportIn(
viewport: Frames,
selection: Frames,
factor: number
): boolean {
if (viewport.start == viewport.end) {
return false;
}
if (selection.start != selection.end) {
const newWidth = Math.round((viewport.end - viewport.start) / factor);
return newWidth > selection.end - selection.start;
}
return true;
}
export function canZoomViewportOut(
viewport: Frames,
numFrames: number
): boolean {
if (viewport.start == viewport.end) {
return false;
}
return viewport.start > 0 || viewport.end < numFrames;
}