mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-10 22:20:14 +00:00
fix(studio): harden keyframe editing semantics
This commit is contained in:
@@ -11,6 +11,21 @@ import {
|
||||
materializeIfDynamic,
|
||||
} from "./gsapDragCommit";
|
||||
|
||||
export function buildTemporalArcKeyframes(
|
||||
anim: GsapAnimation,
|
||||
percentage: number,
|
||||
properties: Record<string, number>,
|
||||
) {
|
||||
return [
|
||||
...(anim.keyframes?.keyframes ?? []).map((keyframe) => ({
|
||||
percentage: keyframe.percentage,
|
||||
properties: { ...keyframe.properties },
|
||||
...(keyframe.ease ? { ease: keyframe.ease } : {}),
|
||||
})),
|
||||
{ percentage, properties },
|
||||
].sort((a, b) => a.percentage - b.percentage);
|
||||
}
|
||||
|
||||
async function extendTweenAndAddKeyframe(
|
||||
selection: DomEditSelection,
|
||||
anim: GsapAnimation,
|
||||
@@ -259,6 +274,47 @@ export async function commitGsapPositionFromDrag(
|
||||
|
||||
const backfillDefaults: Record<string, number> = { x: baseGsapX, y: baseGsapY };
|
||||
const ct = usePlayerStore.getState().currentTime;
|
||||
if (anim.arcPath?.enabled) {
|
||||
const { activeKeyframePct, setActiveKeyframePct } = usePlayerStore.getState();
|
||||
const pct = activeKeyframePct ?? computeCurrentPercentage(selection, anim);
|
||||
const keyframes = anim.keyframes?.keyframes ?? [];
|
||||
const pointIndex = keyframes.findIndex((kf) => Math.abs(kf.percentage - pct) < 0.05);
|
||||
if (pointIndex >= 0) {
|
||||
await callbacks.commitMutation(
|
||||
selection,
|
||||
{
|
||||
type: "update-motion-path-point",
|
||||
animationId: anim.id,
|
||||
pointIndex,
|
||||
x: newX,
|
||||
y: newY,
|
||||
},
|
||||
{ label: "Move layer (waypoint)", softReload: true, beforeReload: restoreOffset },
|
||||
);
|
||||
setActiveKeyframePct(null);
|
||||
parkPlayheadOnKeyframe(anim, pct);
|
||||
return;
|
||||
}
|
||||
|
||||
const tweenStart = resolveTweenStart(anim);
|
||||
const tweenDuration = resolveTweenDuration(anim);
|
||||
if (tweenStart === null || tweenDuration <= 0 || keyframes.length < 2) return;
|
||||
const temporalKeyframes = buildTemporalArcKeyframes(anim, pct, { x: newX, y: newY });
|
||||
await callbacks.commitMutation(
|
||||
selection,
|
||||
{
|
||||
type: "replace-with-keyframes",
|
||||
animationId: anim.id,
|
||||
targetSelector: anim.targetSelector,
|
||||
position: roundTo3(tweenStart),
|
||||
duration: roundTo3(tweenDuration),
|
||||
keyframes: temporalKeyframes,
|
||||
ease: "none",
|
||||
},
|
||||
{ label: "Move layer (new keyframe)", softReload: true, beforeReload: restoreOffset },
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (anim.keyframes) {
|
||||
const newId = await materializeIfDynamic(anim, iframe, callbacks.commitMutation, selection);
|
||||
const effectiveAnim = newId ? { ...anim, id: newId } : anim;
|
||||
|
||||
Reference in New Issue
Block a user