diff options
| author | leimingsheng <leimingsheng@58.com> | 2025-07-21 19:15:52 +0800 |
|---|---|---|
| committer | leimingsheng <leimingsheng@58.com> | 2025-07-21 19:15:52 +0800 |
| commit | d6724e2552d14140017b194e7020252bda73751a (patch) | |
| tree | 0b0b400b7933e21ad911cb2366b1806ff2e35a64 /apps/web/src/stores | |
| parent | 263f14ef2a83b0cc78189f764b0c1859fa392539 (diff) | |
| download | opencut-d6724e2552d14140017b194e7020252bda73751a.tar.gz | |
feat: init timeline zoom
Diffstat (limited to 'apps/web/src/stores')
| -rw-r--r-- | apps/web/src/stores/keybindings-store.ts | 4 | ||||
| -rw-r--r-- | apps/web/src/stores/timeline-store.ts | 20 |
2 files changed, 24 insertions, 0 deletions
diff --git a/apps/web/src/stores/keybindings-store.ts b/apps/web/src/stores/keybindings-store.ts index 60c71afd..f36f2632 100644 --- a/apps/web/src/stores/keybindings-store.ts +++ b/apps/web/src/stores/keybindings-store.ts @@ -25,6 +25,10 @@ export const defaultKeybindings: KeybindingConfig = { "ctrl+z": "undo", "ctrl+shift+z": "redo", "ctrl+y": "redo", + "ctrl+=": "zoom-in", + "ctrl+-": "zoom-out", + "ctrl+0": "zoom-reset", + "ctrl+9": "zoom-fit", delete: "delete-selected", backspace: "delete-selected", }; diff --git a/apps/web/src/stores/timeline-store.ts b/apps/web/src/stores/timeline-store.ts index 1fcfc60e..00bbc743 100644 --- a/apps/web/src/stores/timeline-store.ts +++ b/apps/web/src/stores/timeline-store.ts @@ -158,6 +158,8 @@ interface TimelineStore { // Computed values getTotalDuration: () => number; + getContentWidth: (zoomLevel: number) => number; + calculateFitToWindowZoom: (containerWidth: number) => number; // History actions undo: () => void; @@ -1157,6 +1159,24 @@ export const useTimelineStore = create<TimelineStore>((set, get) => { return Math.max(...trackEndTimes, 0); }, + getContentWidth: (zoomLevel: number) => { + const totalDuration = get().getTotalDuration(); + return totalDuration * TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel; + }, + + calculateFitToWindowZoom: (containerWidth: number) => { + const totalDuration = get().getTotalDuration(); + if (totalDuration === 0) return 1; + + // Leave some padding (10% on each side) + const availableWidth = containerWidth * 0.8; + const requiredWidth = totalDuration * TIMELINE_CONSTANTS.PIXELS_PER_SECOND; + const calculatedZoom = availableWidth / requiredWidth; + + // Clamp between min and max zoom levels + return Math.max(0.1, Math.min(5, calculatedZoom)); + }, + redo: () => { const { redoStack } = get(); if (redoStack.length === 0) return; |
