feat: 实现批量更新机器人数据的功能,优化渲染性能,减少渲染调用次数
This commit is contained in:
parent
0c44af67a0
commit
45b25ac9d3
@ -76,17 +76,73 @@ const monitorScene = async () => {
|
|||||||
// 用于存储 requestAnimationFrame 的 ID,方便在组件卸载或 WebSocket 关闭时取消动画循环。
|
// 用于存储 requestAnimationFrame 的 ID,方便在组件卸载或 WebSocket 关闭时取消动画循环。
|
||||||
let animationFrameId: number;
|
let animationFrameId: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量更新机器人数据,减少渲染调用次数
|
||||||
|
* @param updates 需要更新的机器人数据数组
|
||||||
|
*/
|
||||||
|
const batchUpdateRobots = (updates: Array<{ id: string; data: RobotRealtimeInfo }>) => {
|
||||||
|
if (!editor.value || updates.length === 0) return;
|
||||||
|
|
||||||
|
// 先更新所有机器人的状态信息,包括光圈渲染所需的状态
|
||||||
|
updates.forEach(({ id, data }) => {
|
||||||
|
const { x, y, active, angle, path: points, isWaring, isFault, ...rest } = data;
|
||||||
|
|
||||||
|
// 更新机器人基本信息
|
||||||
|
editor.value?.updateRobot(id, rest);
|
||||||
|
|
||||||
|
// 处理路径坐标转换,参考refreshRobot方法的逻辑
|
||||||
|
let processedPath: Array<{ x: number; y: number }> | undefined;
|
||||||
|
if (points?.length) {
|
||||||
|
// 新路径:相对于机器人中心的坐标
|
||||||
|
const cx = x || 37; // 机器人中心X坐标,默认37
|
||||||
|
const cy = y || 37; // 机器人中心Y坐标,默认37
|
||||||
|
processedPath = points.map((p) => ({ x: p.x - cx, y: p.y - cy }));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新机器人状态,触发光圈渲染
|
||||||
|
const robotState = { active, isWaring, isFault, path: processedPath, angle };
|
||||||
|
if (Object.values(robotState).some((v) => v !== undefined)) {
|
||||||
|
editor.value?.setValue({ id, robot: robotState }, { render: false, history: false, doEvent: false });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 批量设置位置和可见性,只渲染一次
|
||||||
|
const positionUpdates = updates.map(({ id, data }) => {
|
||||||
|
const { x, y, angle } = data;
|
||||||
|
if (isNil(x) || isNil(y)) {
|
||||||
|
return { id, visible: false };
|
||||||
|
} else {
|
||||||
|
const newX = x - 60;
|
||||||
|
const newY = y - 60;
|
||||||
|
const rotate = angle;
|
||||||
|
return { id, x: newX, y: newY, rotate, visible: true };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 使用Meta2D的批量更新方法,减少渲染调用
|
||||||
|
positionUpdates.forEach((update) => {
|
||||||
|
editor.value?.setValue(update, { render: false, history: false, doEvent: false });
|
||||||
|
});
|
||||||
|
|
||||||
|
// 批量更新完成后,统一渲染一次
|
||||||
|
editor.value?.render();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染循环函数。
|
* 渲染循环函数。
|
||||||
* 通过 requestAnimationFrame 以浏览器的刷新频率被调用。
|
* 通过 requestAnimationFrame 以浏览器的刷新频率被调用。
|
||||||
* 采用时间分片(Time Slicing)策略,为每一帧的渲染操作设定一个时间预算(frameBudget),
|
* 采用时间分片(Time Slicing)策略,为每一帧的渲染操作设定一个时间预算(frameBudget),
|
||||||
* 避免单帧处理过多数据导致UI阻塞。
|
* 避免单帧处理过多数据导致UI阻塞。
|
||||||
|
* 新增批量渲染优化,减少渲染调用次数。
|
||||||
*/
|
*/
|
||||||
const renderLoop = () => {
|
const renderLoop = () => {
|
||||||
const frameBudget = 8; // 每一帧的渲染预算,单位:毫秒。保守设置为8ms,为其他任务留出时间。
|
const frameBudget = 8; // 每一帧的渲染预算,单位:毫秒。保守设置为8ms,为其他任务留出时间。
|
||||||
const startTime = performance.now();
|
const startTime = performance.now();
|
||||||
|
|
||||||
// 在时间预算内,持续处理机器人数据
|
// 收集所有需要更新的机器人数据,但不立即渲染
|
||||||
|
const updates: Array<{ id: string; data: RobotRealtimeInfo }> = [];
|
||||||
|
|
||||||
|
// 在时间预算内,持续收集机器人数据
|
||||||
while (performance.now() - startTime < frameBudget && latestRobotData.size > 0) {
|
while (performance.now() - startTime < frameBudget && latestRobotData.size > 0) {
|
||||||
// 获取并移除 Map 中的第一条数据
|
// 获取并移除 Map 中的第一条数据
|
||||||
const entry = latestRobotData.entries().next().value;
|
const entry = latestRobotData.entries().next().value;
|
||||||
@ -94,23 +150,17 @@ const monitorScene = async () => {
|
|||||||
const [id, data] = entry;
|
const [id, data] = entry;
|
||||||
latestRobotData.delete(id);
|
latestRobotData.delete(id);
|
||||||
|
|
||||||
const { x, y, active, angle, path, isWaring, isFault, ...rest } = data;
|
|
||||||
// 确保机器人仍然存在于编辑器中
|
// 确保机器人仍然存在于编辑器中
|
||||||
if (editor.value?.checkRobotById(id)) {
|
if (editor.value?.checkRobotById(id)) {
|
||||||
// 更新机器人的非位置属性(如状态等)
|
updates.push({ id, data });
|
||||||
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 });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 批量更新机器人,减少渲染调用次数
|
||||||
|
if (updates.length > 0) {
|
||||||
|
batchUpdateRobots(updates);
|
||||||
|
}
|
||||||
|
|
||||||
// 处理缓冲的自动门点数据
|
// 处理缓冲的自动门点数据
|
||||||
autoDoorSimulationService.processBufferedData(frameBudget, startTime);
|
autoDoorSimulationService.processBufferedData(frameBudget, startTime);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user