Spaces:
Sleeping
Sleeping
File size: 3,716 Bytes
bc18ad5 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | 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);
}
|