+ {cuts.map((cut, index) => {
+ const leftPercent = duration > 0 ? (cut.time / duration) * 100 : 0;
+ const nextTime = cuts[index + 1]?.time ?? duration;
+ const maxDur = Math.max(0, nextTime - cut.time);
+ const shownDuration =
+ cut.transition.type === "smooth"
+ ? Math.min(cut.transition.duration, maxDur > 0 ? maxDur : cut.transition.duration)
+ : 0;
+ const widthPercent = duration > 0 ? (shownDuration / duration) * 100 : 0;
+ const isSelected = cut.keyframe.id === selectedCutKeyframeId;
+ const fromName =
+ project.cameras.find((c) => c.id === cut.fromCameraId)?.name ?? (cut.fromCameraId ?? "起始");
+ const toName = project.cameras.find((c) => c.id === cut.toCameraId)?.name ?? cut.toCameraId;
+ const transitionLabel =
+ cut.transition.type === "smooth" ? `平滑运镜 ${formatTime(cut.transition.duration)}` : "硬切";
+ return (
+
setSelectedCutKeyframeId(isSelected ? null : cut.keyframe.id)}
+ onKeyDown={(event) => {
+ if (event.key === "Enter" || event.key === " ") {
+ event.preventDefault();
+ setSelectedCutKeyframeId(isSelected ? null : cut.keyframe.id);
+ }
+ }}
+ >
+ {cut.transition.type === "smooth" ? (
+ {formatTime(cut.transition.duration)}
+ ) : null}
+
+ );
+ })}
+ {selectedCut ? (
+
+
+ 类型
+
+ setCameraKeyframeTransition(selectedCut.toCameraId, selectedCut.keyframe.id, {
+ type: value as CameraTransitionType,
+ duration: selectedCut.transition.duration,
+ })
+ }
+ />
+
+
+
时长
+
+
+ setCameraKeyframeTransition(selectedCut.toCameraId, selectedCut.keyframe.id, {
+ type: selectedCut.transition.type,
+ duration: Math.min(
+ MAX_CAMERA_TRANSITION_DURATION,
+ Math.max(MIN_CAMERA_TRANSITION_DURATION, Number(event.target.value))
+ ),
+ })
+ }
+ />
+ 秒
+
+
+
+
+
+
+
+ ) : null}
+