clcik to seek on keyframes

This commit is contained in:
Maze Winther
2026-03-02 16:40:41 +01:00
parent a526066b61
commit 565d2595da
2 changed files with 35 additions and 22 deletions
@@ -259,7 +259,7 @@ export function TimelineElement({
handleKeyframeMouseDown, handleKeyframeMouseDown,
handleKeyframeClick, handleKeyframeClick,
getVisualOffsetPx, getVisualOffsetPx,
} = useKeyframeDrag({ zoomLevel, element }); } = useKeyframeDrag({ zoomLevel, element, displayedStartTime });
const handleRevealInMedia = ({ event }: { event: React.MouseEvent }) => { const handleRevealInMedia = ({ event }: { event: React.MouseEvent }) => {
event.stopPropagation(); event.stopPropagation();
if (hasMediaId(element)) { if (hasMediaId(element)) {
@@ -516,6 +516,7 @@ function KeyframeIndicators({
event: React.MouseEvent; event: React.MouseEvent;
keyframes: SelectedKeyframeRef[]; keyframes: SelectedKeyframeRef[];
orderedKeyframes: SelectedKeyframeRef[]; orderedKeyframes: SelectedKeyframeRef[];
indicatorTime: number;
}) => void; }) => void;
getVisualOffsetPx: (params: { getVisualOffsetPx: (params: {
indicatorTime: number; indicatorTime: number;
@@ -554,12 +555,13 @@ function KeyframeIndicators({
onMouseDown={(event) => onMouseDown={(event) =>
onKeyframeMouseDown({ event, keyframes: indicator.keyframes }) onKeyframeMouseDown({ event, keyframes: indicator.keyframes })
} }
onClick={(event) => onClick={(event) =>
onKeyframeClick({ onKeyframeClick({
event, event,
keyframes: indicator.keyframes, keyframes: indicator.keyframes,
orderedKeyframes, orderedKeyframes,
}) indicatorTime: indicator.time,
})
} }
aria-label="Select keyframe" aria-label="Select keyframe"
> >
@@ -7,7 +7,7 @@ import {
} from "react"; } from "react";
import { useEditor } from "@/hooks/use-editor"; import { useEditor } from "@/hooks/use-editor";
import { useKeyframeSelection } from "./use-keyframe-selection"; import { useKeyframeSelection } from "./use-keyframe-selection";
import { snapTimeToFrame } from "@/lib/time"; import { snapTimeToFrame, getSnappedSeekTime } from "@/lib/time";
import { timelineTimeToSnappedPixels } from "@/lib/timeline"; import { timelineTimeToSnappedPixels } from "@/lib/timeline";
import { import {
DRAG_THRESHOLD_PX, DRAG_THRESHOLD_PX,
@@ -18,7 +18,6 @@ import { BatchCommand } from "@/lib/commands";
import type { SelectedKeyframeRef } from "@/types/animation"; import type { SelectedKeyframeRef } from "@/types/animation";
import type { TimelineElement } from "@/types/timeline"; import type { TimelineElement } from "@/types/timeline";
import type { Command } from "@/lib/commands/base-command"; import type { Command } from "@/lib/commands/base-command";
export interface KeyframeDragState { export interface KeyframeDragState {
isDragging: boolean; isDragging: boolean;
draggingKeyframeIds: Set<string>; draggingKeyframeIds: Set<string>;
@@ -39,9 +38,11 @@ interface PendingKeyframeDrag {
export function useKeyframeDrag({ export function useKeyframeDrag({
zoomLevel, zoomLevel,
element, element,
displayedStartTime,
}: { }: {
zoomLevel: number; zoomLevel: number;
element: TimelineElement; element: TimelineElement;
displayedStartTime: number;
}) { }) {
const editor = useEditor(); const editor = useEditor();
const { const {
@@ -222,10 +223,12 @@ export function useKeyframeDrag({
event, event,
keyframes, keyframes,
orderedKeyframes, orderedKeyframes,
indicatorTime,
}: { }: {
event: ReactMouseEvent; event: ReactMouseEvent;
keyframes: SelectedKeyframeRef[]; keyframes: SelectedKeyframeRef[];
orderedKeyframes: SelectedKeyframeRef[]; orderedKeyframes: SelectedKeyframeRef[];
indicatorTime: number;
}) => { }) => {
event.stopPropagation(); event.stopPropagation();
@@ -234,23 +237,31 @@ export function useKeyframeDrag({
Math.abs(event.clientX - mouseDownXRef.current) > DRAG_THRESHOLD_PX; Math.abs(event.clientX - mouseDownXRef.current) > DRAG_THRESHOLD_PX;
mouseDownXRef.current = null; mouseDownXRef.current = null;
if (wasDrag) return; if (wasDrag) return;
if (event.shiftKey) { const duration = editor.timeline.getTotalDuration();
selectKeyframeRange({ const seekTime = getSnappedSeekTime({
orderedKeyframes, rawTime: displayedStartTime + indicatorTime,
targetKeyframes: keyframes, duration,
isAdditive: event.metaKey || event.ctrlKey, fps,
}); });
return; editor.playback.seek({ time: seekTime });
}
toggleKeyframeSelection({ if (event.shiftKey) {
keyframes, selectKeyframeRange({
isMultiKey: event.metaKey || event.ctrlKey, orderedKeyframes,
}); targetKeyframes: keyframes,
isAdditive: event.metaKey || event.ctrlKey,
});
return;
}
toggleKeyframeSelection({
keyframes,
isMultiKey: event.metaKey || event.ctrlKey,
});
}, },
[toggleKeyframeSelection, selectKeyframeRange], [toggleKeyframeSelection, selectKeyframeRange, editor, displayedStartTime, fps],
); );
const getVisualOffsetPx = useCallback( const getVisualOffsetPx = useCallback(