feat: 在播放控制器中添加场景切换逻辑和时间同步处理,优化播放体验
This commit is contained in:
parent
c5410bb3f5
commit
b49d662e72
@ -13,6 +13,11 @@ type PlaybackMessage = {
|
||||
data: any;
|
||||
};
|
||||
|
||||
type PlaybackSceneData = {
|
||||
json: string;
|
||||
totalDuration: number;
|
||||
};
|
||||
|
||||
// Hook's return type definition
|
||||
export interface UsePlaybackWebSocketReturn {
|
||||
// Connection status
|
||||
@ -75,8 +80,9 @@ export function usePlaybackWebSocket(editorService: ShallowRef<EditorService | u
|
||||
}
|
||||
|
||||
if (msg.type === 'SCENE') {
|
||||
// For seamless scene switching, we only update the scene JSON.
|
||||
// Time and playback state should continue uninterrupted.
|
||||
sceneJson.value = msg.data;
|
||||
latestRobotData.clear();
|
||||
} else if (msg.type === 'AMR') {
|
||||
(msg.data as RobotRealtimeInfo[]).forEach(robot => {
|
||||
latestRobotData.set(robot.id, robot);
|
||||
@ -119,6 +125,9 @@ export function usePlaybackWebSocket(editorService: ShallowRef<EditorService | u
|
||||
};
|
||||
|
||||
const play = () => {
|
||||
// 双重保险:在播放前,强制发送一次SEEK指令,确保后端从正确的时间点开始。
|
||||
// 这可以防止因后端状态不同步或时序问题导致的播放位置错乱。
|
||||
sendCommand(`SEEK:${currentTime.value}`);
|
||||
sendCommand('PLAY');
|
||||
isPlaying.value = true;
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { LockState } from '@meta2d/core';
|
||||
import { message } from 'ant-design-vue';
|
||||
import type { Dayjs } from 'dayjs';
|
||||
import dayjs, { type Dayjs } from 'dayjs';
|
||||
import { isNil } from 'lodash-es';
|
||||
import { computed, onMounted, onUnmounted, provide, ref, type ShallowRef, shallowRef, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
@ -97,6 +97,25 @@ const handleDateChange = (date: Dayjs) => {
|
||||
}
|
||||
};
|
||||
|
||||
const handleSeek = (relativeTime: number) => {
|
||||
if (selectedDate.value) {
|
||||
const absoluteTimestamp = relativeTime + selectedDate.value.startOf('day').valueOf();
|
||||
// 乐观更新,立即将前端时间状态同步到用户选择的时间点
|
||||
playback.currentTime.value = absoluteTimestamp;
|
||||
playback.seek(absoluteTimestamp);
|
||||
}
|
||||
};
|
||||
|
||||
// 监听后台推送的绝对时间戳,如果跨天,则自动更新UI上的日期选择器
|
||||
watch(playback.currentTime, (newTimestamp) => {
|
||||
if (newTimestamp > 0 && selectedDate.value) {
|
||||
const newDate = dayjs(newTimestamp);
|
||||
if (!newDate.isSame(selectedDate.value, 'day')) {
|
||||
selectedDate.value = newDate;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
watch(playback.sceneJson, async (newJson) => {
|
||||
if (newJson) {
|
||||
await editor.value?.load(newJson);
|
||||
@ -662,7 +681,7 @@ const handleGlobalKeydown = (event: KeyboardEvent) => {
|
||||
:total-duration="playback.totalDuration.value"
|
||||
@play="playback.play"
|
||||
@pause="playback.pause"
|
||||
@seek="(time) => playback.seek(time + (selectedDate?.startOf('day').valueOf() ?? 0))"
|
||||
@seek="handleSeek"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
|
Loading…
x
Reference in New Issue
Block a user