diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-02-27 16:33:57 +0100 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-02-27 16:33:57 +0100 |
| commit | 49426f19cd8eaed7cf6c47999b66fee7ee637a56 (patch) | |
| tree | 1b37451529cfcb36e6cae79494c61b9c616077df /apps/web/src/lib/commands/timeline/element/move-elements.ts | |
| parent | 9b94f89def4f96836c4f42a23a73e97fe647a43c (diff) | |
| download | opencut-49426f19cd8eaed7cf6c47999b66fee7ee637a56.tar.gz | |
feat: implement keyframe animation system
Add keyframe support for transform, opacity, and volume properties.
Includes animation engine (interpolation, mutations, resolvers), timeline
markers with selection/snapping, properties panel toggles, keyframe-aware
renderer, and full undo/redo command support.
Also refactor element command constructors to object params, extract
timeline pixel math to pixel-utils.ts, and update cursor rules.
Diffstat (limited to 'apps/web/src/lib/commands/timeline/element/move-elements.ts')
| -rw-r--r-- | apps/web/src/lib/commands/timeline/element/move-elements.ts | 45 |
1 files changed, 32 insertions, 13 deletions
diff --git a/apps/web/src/lib/commands/timeline/element/move-elements.ts b/apps/web/src/lib/commands/timeline/element/move-elements.ts index 2fe06694..973d9cb2 100644 --- a/apps/web/src/lib/commands/timeline/element/move-elements.ts +++ b/apps/web/src/lib/commands/timeline/element/move-elements.ts @@ -14,15 +14,31 @@ import { export class MoveElementCommand extends Command { private savedState: TimelineTrack[] | null = null; + private readonly sourceTrackId: string; + private readonly targetTrackId: string; + private readonly elementId: string; + private readonly newStartTime: number; + private readonly createTrack: { type: TrackType; index: number } | undefined; - constructor( - private sourceTrackId: string, - private targetTrackId: string, - private elementId: string, - private newStartTime: number, - private createTrack?: { type: TrackType; index: number }, - ) { + constructor({ + sourceTrackId, + targetTrackId, + elementId, + newStartTime, + createTrack, + }: { + sourceTrackId: string; + targetTrackId: string; + elementId: string; + newStartTime: number; + createTrack?: { type: TrackType; index: number }; + }) { super(); + this.sourceTrackId = sourceTrackId; + this.targetTrackId = targetTrackId; + this.elementId = elementId; + this.newStartTime = newStartTime; + this.createTrack = createTrack; } execute(): void { @@ -30,10 +46,10 @@ export class MoveElementCommand extends Command { this.savedState = editor.timeline.getTracks(); const sourceTrack = this.savedState.find( - (t) => t.id === this.sourceTrackId, + (track) => track.id === this.sourceTrackId, ); const element = sourceTrack?.elements.find( - (el) => el.id === this.elementId, + (trackElement) => trackElement.id === this.elementId, ); if (!sourceTrack || !element) { @@ -41,7 +57,7 @@ export class MoveElementCommand extends Command { return; } - let targetTrack = this.savedState.find((t) => t.id === this.targetTrackId); + let targetTrack = this.savedState.find((track) => track.id === this.targetTrackId); let tracksToUpdate = this.savedState; if (!targetTrack && this.createTrack) { const newTrack = buildEmptyTrack({ @@ -74,6 +90,7 @@ export class MoveElementCommand extends Command { excludeElementId: this.elementId, }); + // keyframe times remain clip-local, so moving only changes element startTime. const movedElement: TimelineElement = { ...element, startTime: adjustedStartTime, @@ -85,8 +102,8 @@ export class MoveElementCommand extends Command { if (isSameTrack && track.id === this.sourceTrackId) { return { ...track, - elements: track.elements.map((el) => - el.id === this.elementId ? movedElement : el, + elements: track.elements.map((trackElement) => + trackElement.id === this.elementId ? movedElement : trackElement, ), }; } @@ -94,7 +111,9 @@ export class MoveElementCommand extends Command { if (track.id === this.sourceTrackId) { return { ...track, - elements: track.elements.filter((el) => el.id !== this.elementId), + elements: track.elements.filter( + (trackElement) => trackElement.id !== this.elementId, + ), }; } |
