refactor: 优化渲染循环逻辑,采用时间分片策略提升性能,确保流畅动画体验
This commit is contained in:
parent
0728911ef7
commit
0d1308b3b9
@ -76,18 +76,25 @@ const monitorScene = async () => {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 渲染循环函数。
|
* 渲染循环函数。
|
||||||
* 这个函数会通过 requestAnimationFrame 以浏览器的刷新频率(通常是60fps)被反复调用。
|
* 通过 requestAnimationFrame 以浏览器的刷新频率被调用。
|
||||||
* 这是实现流畅动画的核心。
|
* 采用时间分片(Time Slicing)策略,为每一帧的渲染操作设定一个时间预算(frameBudget),
|
||||||
|
* 避免单帧处理过多数据导致UI阻塞。
|
||||||
*/
|
*/
|
||||||
const renderLoop = () => {
|
const renderLoop = () => {
|
||||||
// 检查是否有新的数据需要渲染。如果没有,则本次循环不执行任何操作,节省性能。
|
const frameBudget = 8; // 每一帧的渲染预算,单位:毫秒。保守设置为8ms,为其他任务留出时间。
|
||||||
if (latestRobotData.size > 0) {
|
const startTime = performance.now();
|
||||||
// 遍历所有待更新的机器人数据
|
|
||||||
latestRobotData.forEach((data, id) => {
|
|
||||||
const { x, y, active, angle, path, isWaring, isFault, ...rest } = data;
|
|
||||||
// 确保机器人仍然存在于编辑器中
|
|
||||||
if (!editor.value?.checkRobotById(id)) return;
|
|
||||||
|
|
||||||
|
// 在时间预算内,持续处理数据
|
||||||
|
while (performance.now() - startTime < frameBudget && latestRobotData.size > 0) {
|
||||||
|
// 获取并移除 Map 中的第一条数据
|
||||||
|
const entry = latestRobotData.entries().next().value;
|
||||||
|
if (!entry) break;
|
||||||
|
const [id, data] = entry;
|
||||||
|
latestRobotData.delete(id);
|
||||||
|
|
||||||
|
const { x, y, active, angle, path, isWaring, isFault, ...rest } = data;
|
||||||
|
// 确保机器人仍然存在于编辑器中
|
||||||
|
if (editor.value?.checkRobotById(id)) {
|
||||||
// 更新机器人的非位置属性(如状态等)
|
// 更新机器人的非位置属性(如状态等)
|
||||||
editor.value?.updateRobot(id, rest);
|
editor.value?.updateRobot(id, rest);
|
||||||
|
|
||||||
@ -99,11 +106,11 @@ const monitorScene = async () => {
|
|||||||
// 如果坐标有效,则刷新机器人在画布上的位置、角度等
|
// 如果坐标有效,则刷新机器人在画布上的位置、角度等
|
||||||
editor.value.refreshRobot(id, { x, y, active, angle, path, isWaring, isFault });
|
editor.value.refreshRobot(id, { x, y, active, angle, path, isWaring, isFault });
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
// 本次渲染完成后,清空数据缓冲区,等待下一批新数据的到来。
|
|
||||||
latestRobotData.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 请求浏览器在下一次重绘之前再次调用 renderLoop,形成动画循环。
|
// 请求浏览器在下一次重绘之前再次调用 renderLoop,形成动画循环。
|
||||||
|
// 即使本帧没有处理完所有数据,下一帧也会继续处理剩余的数据。
|
||||||
animationFrameId = requestAnimationFrame(renderLoop);
|
animationFrameId = requestAnimationFrame(renderLoop);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user