summaryrefslogtreecommitdiff
path: root/apps/web/src/hooks/use-timeline-zoom.ts
diff options
context:
space:
mode:
authorgantiro <gantiro396@gmail.com>2025-07-15 22:51:38 +0700
committergantiro <gantiro396@gmail.com>2025-07-15 22:51:38 +0700
commitb266678fe4bb8c4053688fd037693fa2f930ac14 (patch)
tree89a8c3b7a151a42fecfc480b440c55fce79252da /apps/web/src/hooks/use-timeline-zoom.ts
parent1f95bb98d6108a5fa059e0f9a08c98e5bdb72c08 (diff)
downloadopencut-b266678fe4bb8c4053688fd037693fa2f930ac14.tar.gz
Optimize timeline performance
Diffstat (limited to 'apps/web/src/hooks/use-timeline-zoom.ts')
-rw-r--r--apps/web/src/hooks/use-timeline-zoom.ts74
1 files changed, 45 insertions, 29 deletions
diff --git a/apps/web/src/hooks/use-timeline-zoom.ts b/apps/web/src/hooks/use-timeline-zoom.ts
index ce32c9f0..16d20d7e 100644
--- a/apps/web/src/hooks/use-timeline-zoom.ts
+++ b/apps/web/src/hooks/use-timeline-zoom.ts
@@ -1,4 +1,5 @@
-import { useState, useCallback, useEffect, RefObject } from "react";
+import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
+import { useState, useCallback, RefObject, useMemo } from "react";
interface UseTimelineZoomProps {
containerRef: RefObject<HTMLDivElement>;
@@ -7,48 +8,63 @@ interface UseTimelineZoomProps {
interface UseTimelineZoomReturn {
zoomLevel: number;
+ zoomStep: number;
setZoomLevel: (zoomLevel: number | ((prev: number) => number)) => void;
+ handleChangeZoomStep: (zoomStep: number) => void;
+ handleChangeZoomLevel: (zoomStep: number) => void;
handleWheel: (e: React.WheelEvent) => void;
}
-export function useTimelineZoom({
- containerRef,
- isInTimeline = false,
-}: UseTimelineZoomProps): UseTimelineZoomReturn {
+export function useTimelineZoom(): UseTimelineZoomReturn {
const [zoomLevel, setZoomLevel] = useState(1);
+ const zoomStep = useMemo(
+ () =>
+ Math.max(1, Math.round(zoomLevel / TIMELINE_CONSTANTS.ZOOM_STEP_BASE)),
+ [zoomLevel]
+ );
+
+ const handleChangeZoomStep = useCallback((newStep: number) => {
+ setZoomLevel(
+ Math.max(
+ TIMELINE_CONSTANTS.ZOOM_LEVEL_MIN,
+ newStep * TIMELINE_CONSTANTS.ZOOM_STEP_BASE
+ )
+ );
+ }, []);
+
+ const handleChangeZoomLevel = useCallback((newLevel: number) => {
+ setZoomLevel(
+ Math.max(
+ TIMELINE_CONSTANTS.ZOOM_LEVEL_MIN,
+ Math.min(TIMELINE_CONSTANTS.ZOOM_LEVEL_MAX, newLevel)
+ )
+ );
+ }, []);
+
+ // Mouse wheel zoom, ctrl/meta gesture
const handleWheel = useCallback((e: React.WheelEvent) => {
- // Only zoom if user is using pinch gesture (ctrlKey or metaKey is true)
if (e.ctrlKey || e.metaKey) {
- e.preventDefault();
- const delta = e.deltaY > 0 ? -0.15 : 0.15;
- setZoomLevel((prev) => Math.max(0.1, Math.min(10, prev + delta)));
+ e.preventDefault?.();
+ const delta =
+ e.deltaY > 0
+ ? -TIMELINE_CONSTANTS.ZOOM_STEP_BASE
+ : TIMELINE_CONSTANTS.ZOOM_STEP_BASE;
+ setZoomLevel((prev) =>
+ Math.max(
+ TIMELINE_CONSTANTS.ZOOM_LEVEL_MIN,
+ Math.min(TIMELINE_CONSTANTS.ZOOM_LEVEL_MAX, prev + delta)
+ )
+ );
}
- // Otherwise, allow normal scrolling
}, []);
- // Prevent browser zooming in/out when in timeline
- useEffect(() => {
- const preventZoom = (e: WheelEvent) => {
- if (
- isInTimeline &&
- (e.ctrlKey || e.metaKey) &&
- containerRef.current?.contains(e.target as Node)
- ) {
- e.preventDefault();
- }
- };
-
- document.addEventListener("wheel", preventZoom, { passive: false });
-
- return () => {
- document.removeEventListener("wheel", preventZoom);
- };
- }, [isInTimeline, containerRef]);
-
return {
zoomLevel,
+ zoomStep,
setZoomLevel,
+ handleChangeZoomStep,
+ handleChangeZoomLevel,
handleWheel,
};
}