From 98b2103286f04d67db1d57f9e3330efa5d41fdb7 Mon Sep 17 00:00:00 2001 From: Simon Orzel Date: Thu, 17 Jul 2025 02:25:24 +0200 Subject: feat: working --- .../components/editor/timeline/timeline-ruler.tsx | 137 +++++++++++---------- 1 file changed, 71 insertions(+), 66 deletions(-) (limited to 'apps/web/src/components/editor/timeline/timeline-ruler.tsx') diff --git a/apps/web/src/components/editor/timeline/timeline-ruler.tsx b/apps/web/src/components/editor/timeline/timeline-ruler.tsx index 85972089..07a4ad5d 100644 --- a/apps/web/src/components/editor/timeline/timeline-ruler.tsx +++ b/apps/web/src/components/editor/timeline/timeline-ruler.tsx @@ -1,3 +1,4 @@ +import { useMemo } from "react"; import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants"; import { useTimelinePlayheadRuler } from "./timeline-playhead"; @@ -38,82 +39,86 @@ export function TimelineRuler({ playheadRef, }); + // Memoize the expensive ruler markers calculation + const rulerMarkers = useMemo(() => { + // Calculate appropriate time interval based on zoom level + const getTimeInterval = (zoom: number) => { + const pixelsPerSecond = TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoom; + if (pixelsPerSecond >= 200) return 0.1; // Every 0.1s when very zoomed in + if (pixelsPerSecond >= 100) return 0.5; // Every 0.5s when zoomed in + if (pixelsPerSecond >= 50) return 1; // Every 1s at normal zoom + if (pixelsPerSecond >= 25) return 2; // Every 2s when zoomed out + if (pixelsPerSecond >= 12) return 5; // Every 5s when more zoomed out + if (pixelsPerSecond >= 6) return 10; // Every 10s when very zoomed out + return 30; // Every 30s when extremely zoomed out + }; + + const formatTime = (seconds: number, interval: number) => { + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + const secs = seconds % 60; + + if (hours > 0) { + return `${hours}:${minutes.toString().padStart(2, "0")}:${Math.floor(secs).toString().padStart(2, "0")}`; + } else if (minutes > 0) { + return `${minutes}:${Math.floor(secs).toString().padStart(2, "0")}`; + } else if (interval >= 1) { + return `${Math.floor(secs)}s`; + } else { + return `${secs.toFixed(1)}s`; + } + }; + + const interval = getTimeInterval(zoomLevel); + const markerCount = Math.ceil(duration / interval) + 1; + const markers = []; + + for (let i = 0; i < markerCount; i++) { + const time = i * interval; + if (time > duration) break; + + const isMainMarker = time % (interval >= 1 ? Math.max(1, interval) : 1) === 0; + const leftPosition = time * TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel; + + markers.push( +
+ + {formatTime(time, interval)} + +
+ ); + } + + return markers; + }, [duration, zoomLevel]); // Only recalculate when duration or zoomLevel changes + return (
- {(() => { - // Calculate appropriate time interval based on zoom level - const getTimeInterval = (zoom: number) => { - const pixelsPerSecond = - TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoom; - if (pixelsPerSecond >= 200) return 0.1; // Every 0.1s when very zoomed in - if (pixelsPerSecond >= 100) return 0.5; // Every 0.5s when zoomed in - if (pixelsPerSecond >= 50) return 1; // Every 1s at normal zoom - if (pixelsPerSecond >= 25) return 2; // Every 2s when zoomed out - if (pixelsPerSecond >= 12) return 5; // Every 5s when more zoomed out - if (pixelsPerSecond >= 6) return 10; // Every 10s when very zoomed out - return 30; // Every 30s when extremely zoomed out - }; - - const interval = getTimeInterval(zoomLevel); - const markerCount = Math.ceil(duration / interval) + 1; - - return Array.from({ length: markerCount }, (_, i) => { - const time = i * interval; - if (time > duration) return null; - - const isMainMarker = - time % (interval >= 1 ? Math.max(1, interval) : 1) === 0; - - return ( -
- - {(() => { - const formatTime = (seconds: number) => { - const hours = Math.floor(seconds / 3600); - const minutes = Math.floor((seconds % 3600) / 60); - const secs = seconds % 60; - - if (hours > 0) { - return `${hours}:${minutes.toString().padStart(2, "0")}:${Math.floor(secs).toString().padStart(2, "0")}`; - } else if (minutes > 0) { - return `${minutes}:${Math.floor(secs).toString().padStart(2, "0")}`; - } else if (interval >= 1) { - return `${Math.floor(secs)}s`; - } else { - return `${secs.toFixed(1)}s`; - } - }; - return formatTime(time); - })()} - -
- ); - }).filter(Boolean); - })()} + {rulerMarkers}
); -- cgit v1.3.1