feat: 优化时间轴

This commit is contained in:
2026-09-18 00:52:28 +08:00
parent e66e3374bf
commit 8645ea3007
19 changed files with 1539 additions and 392 deletions

View File

@@ -362,6 +362,39 @@ export function scaleCameraKeyframeTimes(times: number[], newEnd: number, durati
return scaled;
}
/**
* 拖动运镜片段左端把手(修剪起点):与右端把手完全对称 —— 末帧固定不动,
* 首帧落到 newStart,其余关键帧按同一比例缩放,各帧之间的相对节奏不变。
* newStart 夹在「0 ~ 末帧 - 最小跨度」之间。
*/
export function scaleCameraKeyframeStart(times: number[], newStart: number, duration: number): number[] {
const count = times.length;
if (count < 2) return times;
const end = times[count - 1];
const start = times[0];
const currentSpan = end - start;
if (!Number.isFinite(currentSpan) || currentSpan <= 0) return times;
// 缩放上界:末帧不动,首帧最多贴到「末帧 - 最小跨度」处,保证各帧还能依次排开
const minSpan = CAMERA_KEYFRAME_MIN_GAP * (count - 1);
const upper = Math.max(Math.min(end - minSpan, duration), 0);
const nextStart = Math.min(Math.max(newStart, 0), upper);
if (Math.abs(nextStart - start) < 1e-6) return times;
const ratio = (end - nextStart) / currentSpan;
const scaled = times.map((value, index) => {
if (index === count - 1) return end;
const next = end - (end - value) * ratio;
// 这一帧之后还剩 count-1-index 帧,各自要留够最小间隔
const ceiling = end - CAMERA_KEYFRAME_MIN_GAP * (count - 1 - index);
return Math.max(Math.min(next, ceiling), nextStart);
});
scaled[0] = nextStart;
return scaled;
}
/**
* 一次性覆盖整条运镜轨道的所有关键帧时间(按索引对应,最后统一按时间重排)。
* 拖动把手 / 拖动关键帧都走这里,避免逐个更新时反复排序导致索引错位。