feat: 在播放控制器中添加动画帧定时器逻辑,优化播放时间更新和自动暂停功能

This commit is contained in:
xudan 2025-10-09 10:01:38 +08:00
parent caadef3a92
commit 58e0726a7f

View File

@ -1,6 +1,6 @@
<script setup lang="ts">
import { CaretRightOutlined, PauseOutlined } from '@ant-design/icons-vue';
import { computed, ref, watch } from 'vue';
import { computed, ref, watch, onUnmounted } from 'vue';
import { useTimelineTicks } from '../hooks/useTimelineTicks';
@ -35,14 +35,66 @@ const { ticks } = useTimelineTicks(viewStartTime, viewEndTime);
watch(
() => props.currentTime,
(newValue) => {
internalCurrentTime.value = newValue;
// Only update from prop if not playing
if (!props.isPlaying) {
internalCurrentTime.value = newValue;
}
const newHour = Math.floor(newValue / HOUR_IN_MS);
if (newHour !== selectedHour.value) {
selectedHour.value = newHour;
}
},
{ immediate: true },
);
// --- Animation Frame Timer for Playback ---
let animationFrameId: number | null = null;
let lastTimestamp: number | null = null;
const animationLoop = (timestamp: number) => {
if (!lastTimestamp) {
lastTimestamp = timestamp;
}
const deltaTime = timestamp - lastTimestamp;
lastTimestamp = timestamp;
// Ensure we don't jump too far ahead if the tab was inactive
const clampedDelta = Math.min(deltaTime, 1000); // Max 1-second jump
const newTime = internalCurrentTime.value + clampedDelta;
if (newTime < props.totalDuration) {
internalCurrentTime.value = newTime;
// No need to emit timeupdate as per user decision
// emit('timeupdate', newTime);
animationFrameId = requestAnimationFrame(animationLoop);
} else {
internalCurrentTime.value = props.totalDuration;
emit('pause'); // Auto-pause at the end
}
};
watch(
() => props.isPlaying,
(isPlaying) => {
if (isPlaying) {
lastTimestamp = null; // Reset timestamp on play
animationFrameId = requestAnimationFrame(animationLoop);
} else {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
animationFrameId = null;
}
}
},
);
onUnmounted(() => {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
}
});
// --- Computed properties for display and binding ---
const formatTime = (ms: number): string => {
if (isNaN(ms) || ms < 0) return '00:00:00';