feat: 优化机器人状态监控,采用 requestAnimationFrame 实现高效渲染,提升动画流畅性并避免UI阻塞

This commit is contained in:
xudan 2025-07-26 04:30:43 +08:00
parent 3192cb814e
commit 2f3bfa9bc4

View File

@ -47,6 +47,7 @@ const readScene = async () => {
/**
* 监控场景中的机器人状态
* 采用 requestAnimationFrame 优化高频数据渲染确保动画流畅且不阻塞UI线程
*/
const monitorScene = async () => {
console.log(current.value?.id);
@ -54,17 +55,74 @@ const monitorScene = async () => {
// 使
const ws = isMonitorMode.value ? await monitorRealSceneById(props.sid) : await monitorSceneById(props.sid);
if (isNil(ws)) return;
// 使 Map
// Key IDValue
//
const latestRobotData = new Map<string, RobotRealtimeInfo>();
// requestAnimationFrame ID便 WebSocket
let animationFrameId: number;
/**
* 渲染循环函数
* 这个函数会通过 requestAnimationFrame 以浏览器的刷新频率通常是60fps被反复调用
* 这是实现流畅动画的核心
*/
const renderLoop = () => {
//
if (latestRobotData.size > 0) {
//
latestRobotData.forEach((data, id) => {
const { x, y, active, angle, path, isWaring, isFault, ...rest } = data;
//
if (!editor.value?.checkRobotById(id)) return;
//
editor.value?.updateRobot(id, rest);
//
if (isNil(x) || isNil(y)) {
//
editor.value.updatePen(id, { visible: false });
} else {
//
editor.value.refreshRobot(id, { x, y, active, angle, path, isWaring, isFault });
}
});
//
latestRobotData.clear();
}
// renderLoop
animationFrameId = requestAnimationFrame(renderLoop);
};
/**
* WebSocket onmessage 事件处理器
* 这个函数只做一件事接收数据并将其快速存入缓冲区
* 这种数据与渲染分离的设计是避免UI阻塞的关键
*/
ws.onmessage = (e) => {
const { id, x, y, active, angle, path, isWaring, isFault, ...rest } = <RobotRealtimeInfo>JSON.parse(e.data || '{}');
if (!editor.value?.checkRobotById(id)) return;
editor.value?.updateRobot(id, rest);
if (isNil(x) || isNil(y)) {
editor.value.updatePen(id, { visible: false });
} else {
editor.value.refreshRobot(id, { x, y, active, angle, path, isWaring, isFault });
const data = <RobotRealtimeInfo>JSON.parse(e.data || '{}');
// MapID
latestRobotData.set(data.id, data);
};
client.value = ws;
// WebSocket
renderLoop();
// WebSocket onclose
const originalOnClose = ws.onclose;
ws.onclose = (event) => {
//
cancelAnimationFrame(animationFrameId);
// onclose
if (originalOnClose) {
originalOnClose.call(ws, event);
}
};
client.value = ws;
};
//#endregion