From c3f0d640ef366fe4d94ff995ee8fe5ef282b9c1e Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 2 Feb 2026 18:11:12 +0100 Subject: feat: exponential zoom --- apps/web/src/lib/timeline/zoom-utils.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'apps/web/src/lib') diff --git a/apps/web/src/lib/timeline/zoom-utils.ts b/apps/web/src/lib/timeline/zoom-utils.ts index 49f7fcb6..c4a64ed1 100644 --- a/apps/web/src/lib/timeline/zoom-utils.ts +++ b/apps/web/src/lib/timeline/zoom-utils.ts @@ -51,3 +51,36 @@ export function getZoomPercent({ }): 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); +} -- cgit v1.3.1 From e88a059222470d6b5e40baf1d81a314940a98955 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 2 Feb 2026 19:14:37 +0100 Subject: increase zoom of buttons + refactor --- apps/web/src/components/editor/timeline/timeline-toolbar.tsx | 12 +++++++----- apps/web/src/constants/timeline-constants.tsx | 4 +--- apps/web/src/lib/timeline/zoom-utils.ts | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'apps/web/src/lib') diff --git a/apps/web/src/components/editor/timeline/timeline-toolbar.tsx b/apps/web/src/components/editor/timeline/timeline-toolbar.tsx index 33cf83ae..6ac6fba5 100644 --- a/apps/web/src/components/editor/timeline/timeline-toolbar.tsx +++ b/apps/web/src/components/editor/timeline/timeline-toolbar.tsx @@ -51,11 +51,13 @@ export function TimelineToolbar({ setZoomLevel: ({ zoom }: { zoom: number }) => void; }) { const handleZoom = ({ direction }: { direction: "in" | "out" }) => { - const zoomFactor = 1.25; const newZoomLevel = direction === "in" - ? Math.min(TIMELINE_CONSTANTS.ZOOM_MAX, zoomLevel * zoomFactor) - : Math.max(minZoom, zoomLevel / zoomFactor); + ? Math.min( + TIMELINE_CONSTANTS.ZOOM_MAX, + zoomLevel * TIMELINE_CONSTANTS.ZOOM_BUTTON_FACTOR, + ) + : Math.max(minZoom, zoomLevel / TIMELINE_CONSTANTS.ZOOM_BUTTON_FACTOR); setZoomLevel({ zoom: newZoomLevel }); }; @@ -297,7 +299,7 @@ function ToolbarRightSection({ type="button" onClick={() => onZoom({ direction: "out" })} > - + onZoom({ direction: "in" })} > - + diff --git a/apps/web/src/constants/timeline-constants.tsx b/apps/web/src/constants/timeline-constants.tsx index 692ccd65..e467de41 100644 --- a/apps/web/src/constants/timeline-constants.tsx +++ b/apps/web/src/constants/timeline-constants.tsx @@ -35,12 +35,10 @@ export const TRACK_GAP = 4; export const TIMELINE_CONSTANTS = { PIXELS_PER_SECOND: 50, DEFAULT_ELEMENT_DURATION: 5, - PLAYHEAD_LOOKAHEAD_SECONDS: 30, // padding ahead PADDING_TOP_PX: 0, - ZOOM_LEVELS: [0.1, 0.25, 0.5, 1, 1.5, 2, 3, 4, 6, 8, 10, 15, 20, 30, 50], ZOOM_MIN: 0.1, ZOOM_MAX: 100, - ZOOM_STEP: 0.1, + ZOOM_BUTTON_FACTOR: 1.7, } as const; export const DEFAULT_TIMELINE_VIEW_STATE: TTimelineViewState = { diff --git a/apps/web/src/lib/timeline/zoom-utils.ts b/apps/web/src/lib/timeline/zoom-utils.ts index c4a64ed1..a299edb3 100644 --- a/apps/web/src/lib/timeline/zoom-utils.ts +++ b/apps/web/src/lib/timeline/zoom-utils.ts @@ -53,8 +53,8 @@ export function getZoomPercent({ } /** - * Convert linear slider position (0-1) to exponential zoom level. - * At low slider values, zoom changes are small. At high values, changes are large. + * 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, -- cgit v1.3.1 From 1aec9c5cf5112fb3def79bec291540ff5c78e057 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 2 Feb 2026 19:15:25 +0100 Subject: fix comment --- apps/web/src/lib/timeline/zoom-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'apps/web/src/lib') diff --git a/apps/web/src/lib/timeline/zoom-utils.ts b/apps/web/src/lib/timeline/zoom-utils.ts index a299edb3..bbc0b6ae 100644 --- a/apps/web/src/lib/timeline/zoom-utils.ts +++ b/apps/web/src/lib/timeline/zoom-utils.ts @@ -70,7 +70,7 @@ export function sliderToZoom({ } /** - * Convert exponential zoom level to linear slider position (0-1). + * convert exponential zoom level to linear slider position (0-1). */ export function zoomToSlider({ zoomLevel, -- cgit v1.3.1