mirror of
https://github.com/OpenCut-app/OpenCut.git
synced 2026-07-13 21:52:53 +02:00
87 lines
2.2 KiB
TypeScript
87 lines
2.2 KiB
TypeScript
import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
|
|
|
|
const PADDING_MAX_RATIO = 0.75;
|
|
const PADDING_MIN_RATIO = 0.15;
|
|
const PADDING_MIN_AT_ZOOM_PERCENT = 0.2;
|
|
|
|
export function getTimelineZoomMin({
|
|
duration,
|
|
containerWidth,
|
|
}: {
|
|
duration: number;
|
|
containerWidth: number | null | undefined;
|
|
}): number {
|
|
const safeDuration = Math.max(duration, 1);
|
|
const safeContainerWidth = containerWidth ?? 1000;
|
|
const contentRatioAtMinZoom = 1 - PADDING_MAX_RATIO;
|
|
const availableWidth = safeContainerWidth * contentRatioAtMinZoom;
|
|
const zoomToFit =
|
|
availableWidth / (safeDuration * TIMELINE_CONSTANTS.PIXELS_PER_SECOND);
|
|
|
|
return Math.min(TIMELINE_CONSTANTS.ZOOM_MAX, zoomToFit);
|
|
}
|
|
|
|
export function getTimelinePaddingPx({
|
|
containerWidth,
|
|
zoomLevel,
|
|
minZoom,
|
|
}: {
|
|
containerWidth: number;
|
|
zoomLevel: number;
|
|
minZoom: number;
|
|
}): number {
|
|
const zoomPercent = getZoomPercent({ zoomLevel, minZoom });
|
|
const paddingTransitionPercent = Math.min(
|
|
zoomPercent / PADDING_MIN_AT_ZOOM_PERCENT,
|
|
1,
|
|
);
|
|
const paddingRatio =
|
|
PADDING_MAX_RATIO -
|
|
(PADDING_MAX_RATIO - PADDING_MIN_RATIO) * paddingTransitionPercent;
|
|
|
|
return containerWidth * paddingRatio;
|
|
}
|
|
|
|
export function getZoomPercent({
|
|
zoomLevel,
|
|
minZoom,
|
|
}: {
|
|
zoomLevel: number;
|
|
minZoom: number;
|
|
}): number {
|
|
return (zoomLevel - minZoom) / (TIMELINE_CONSTANTS.ZOOM_MAX - minZoom);
|
|
}
|
|
|
|
/**
|
|
* convert linear slider position (0-1) to exponential zoom level.
|
|
* at low slider values, zoom changes are small. at high values, changes are large.
|
|
*/
|
|
export function sliderToZoom({
|
|
sliderPosition,
|
|
minZoom,
|
|
maxZoom = TIMELINE_CONSTANTS.ZOOM_MAX,
|
|
}: {
|
|
sliderPosition: number;
|
|
minZoom: number;
|
|
maxZoom?: number;
|
|
}): number {
|
|
const clampedPosition = Math.max(0, Math.min(1, sliderPosition));
|
|
return minZoom * (maxZoom / minZoom) ** clampedPosition;
|
|
}
|
|
|
|
/**
|
|
* convert exponential zoom level to linear slider position (0-1).
|
|
*/
|
|
export function zoomToSlider({
|
|
zoomLevel,
|
|
minZoom,
|
|
maxZoom = TIMELINE_CONSTANTS.ZOOM_MAX,
|
|
}: {
|
|
zoomLevel: number;
|
|
minZoom: number;
|
|
maxZoom?: number;
|
|
}): number {
|
|
const clampedZoom = Math.max(minZoom, Math.min(maxZoom, zoomLevel));
|
|
return Math.log(clampedZoom / minZoom) / Math.log(maxZoom / minZoom);
|
|
}
|