feat: 在播放控制器中添加场景切换逻辑和时间同步处理,优化播放体验
This commit is contained in:
parent
c5410bb3f5
commit
b49d662e72
@ -13,6 +13,11 @@ type PlaybackMessage = {
|
|||||||
data: any;
|
data: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type PlaybackSceneData = {
|
||||||
|
json: string;
|
||||||
|
totalDuration: number;
|
||||||
|
};
|
||||||
|
|
||||||
// Hook's return type definition
|
// Hook's return type definition
|
||||||
export interface UsePlaybackWebSocketReturn {
|
export interface UsePlaybackWebSocketReturn {
|
||||||
// Connection status
|
// Connection status
|
||||||
@ -75,8 +80,9 @@ export function usePlaybackWebSocket(editorService: ShallowRef<EditorService | u
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (msg.type === 'SCENE') {
|
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;
|
sceneJson.value = msg.data;
|
||||||
latestRobotData.clear();
|
|
||||||
} else if (msg.type === 'AMR') {
|
} else if (msg.type === 'AMR') {
|
||||||
(msg.data as RobotRealtimeInfo[]).forEach(robot => {
|
(msg.data as RobotRealtimeInfo[]).forEach(robot => {
|
||||||
latestRobotData.set(robot.id, robot);
|
latestRobotData.set(robot.id, robot);
|
||||||
@ -119,6 +125,9 @@ export function usePlaybackWebSocket(editorService: ShallowRef<EditorService | u
|
|||||||
};
|
};
|
||||||
|
|
||||||
const play = () => {
|
const play = () => {
|
||||||
|
// 双重保险:在播放前,强制发送一次SEEK指令,确保后端从正确的时间点开始。
|
||||||
|
// 这可以防止因后端状态不同步或时序问题导致的播放位置错乱。
|
||||||
|
sendCommand(`SEEK:${currentTime.value}`);
|
||||||
sendCommand('PLAY');
|
sendCommand('PLAY');
|
||||||
isPlaying.value = true;
|
isPlaying.value = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { LockState } from '@meta2d/core';
|
import { LockState } from '@meta2d/core';
|
||||||
import { message } from 'ant-design-vue';
|
import { message } from 'ant-design-vue';
|
||||||
import type { Dayjs } from 'dayjs';
|
import dayjs, { type Dayjs } from 'dayjs';
|
||||||
import { isNil } from 'lodash-es';
|
import { isNil } from 'lodash-es';
|
||||||
import { computed, onMounted, onUnmounted, provide, ref, type ShallowRef, shallowRef, watch } from 'vue';
|
import { computed, onMounted, onUnmounted, provide, ref, type ShallowRef, shallowRef, watch } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
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) => {
|
watch(playback.sceneJson, async (newJson) => {
|
||||||
if (newJson) {
|
if (newJson) {
|
||||||
await editor.value?.load(newJson);
|
await editor.value?.load(newJson);
|
||||||
@ -662,7 +681,7 @@ const handleGlobalKeydown = (event: KeyboardEvent) => {
|
|||||||
:total-duration="playback.totalDuration.value"
|
:total-duration="playback.totalDuration.value"
|
||||||
@play="playback.play"
|
@play="playback.play"
|
||||||
@pause="playback.pause"
|
@pause="playback.pause"
|
||||||
@seek="(time) => playback.seek(time + (selectedDate?.startOf('day').valueOf() ?? 0))"
|
@seek="handleSeek"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user