3v324v23's picture
upload
bc18ad5
import { findIndex } from "./search";
import {
FRAME_INTERVAL,
PREVIEW_FRAME_WIDTH,
TIMELINE_OFFSET_X
} from "../constants/constants";
import { ITimelineScaleState } from "@designcombo/types";
import { TIMELINE_ZOOM_LEVELS } from "../constants/scale";
export function getPreviousZoomLevel(
currentZoom: ITimelineScaleState
): ITimelineScaleState {
const previousZoom = getPreviousZoom(currentZoom);
return previousZoom || TIMELINE_ZOOM_LEVELS[0];
}
export function getZoomByIndex(index: number) {
return TIMELINE_ZOOM_LEVELS[index];
}
export function getNextZoomLevel(
currentZoom: ITimelineScaleState
): ITimelineScaleState {
const nextZoom = getNextZoom(currentZoom);
return nextZoom || TIMELINE_ZOOM_LEVELS[TIMELINE_ZOOM_LEVELS.length - 1];
}
export const getPreviousZoom = (
currentZoom: ITimelineScaleState
): ITimelineScaleState | null => {
// Filter zoom levels that are smaller than the current zoom
const smallerZoomLevels = TIMELINE_ZOOM_LEVELS.filter(
(level) => level.zoom < currentZoom.zoom
);
// If there are no smaller zoom levels, return null (no previous zoom)
if (smallerZoomLevels.length === 0) {
return null;
}
// Get the zoom level with the largest zoom value that's still smaller than the current zoom
const previousZoom = smallerZoomLevels.reduce((prev, curr) =>
curr.zoom > prev.zoom ? curr : prev
);
return previousZoom;
};
export const getNextZoom = (
currentZoom: ITimelineScaleState
): ITimelineScaleState | null => {
// Filter zoom levels that are larger than the current zoom
const largerZoomLevels = TIMELINE_ZOOM_LEVELS.filter(
(level) => level.zoom > currentZoom.zoom
);
// If there are no larger zoom levels, return null (no next zoom)
if (largerZoomLevels.length === 0) {
return null;
}
// Get the zoom level with the smallest zoom value that's still larger than the current zoom
const nextZoom = largerZoomLevels.reduce((prev, curr) =>
curr.zoom < prev.zoom ? curr : prev
);
return nextZoom;
};
export function getFitZoomLevel(
totalLengthMs: number,
zoom = 1,
scrollOffset = 8 // Default fallback value
): ITimelineScaleState {
const getVisibleWidth = () => {
const clampedScrollOffset = Math.max(0, scrollOffset);
const timelineCanvas = document.getElementById(
"designcombo-timeline-canvas"
) as HTMLElement;
const offsetWidth =
timelineCanvas?.offsetWidth ?? document.body.offsetWidth;
// Use 1 to prevent NaN because of dividing by 0.
return Math.max(1, offsetWidth - clampedScrollOffset);
};
const getFullWidth = () => {
if (typeof totalLengthMs === "number") {
return timeMsToUnits(totalLengthMs, zoom);
}
return calculateTimelineWidth(totalLengthMs, zoom);
};
const multiplier = getVisibleWidth() / getFullWidth();
const targetZoom = zoom * multiplier;
const fitZoomIndex = findIndex(TIMELINE_ZOOM_LEVELS, (level) => {
return level.zoom > targetZoom;
});
// const clampedIndex = clamp(fitZoomIndex, 0, TIMELINE_ZOOM_LEVELS.length - 1);
return {
segments: 5,
index: fitZoomIndex,
zoom: targetZoom,
unit: 1 / targetZoom
};
}
export function timeMsToUnits(timeMs: number, zoom = 1): number {
const zoomedFrameWidth = PREVIEW_FRAME_WIDTH * zoom;
const frames = timeMs * (60 / 1000);
return frames * zoomedFrameWidth;
}
export function unitsToTimeMs(units: number, zoom = 1): number {
const zoomedFrameWidth = PREVIEW_FRAME_WIDTH * zoom;
const frames = units / zoomedFrameWidth;
return frames * FRAME_INTERVAL;
}
export function calculateTimelineWidth(
totalLengthMs: number,
zoom = 1
): number {
return timeMsToUnits(totalLengthMs, zoom);
}