6.0 KiB
6.0 KiB
库位渲染与状态集成说明
本文档说明当前项目中“库位网格”在 Meta2D 渲染链路中的实现方式、扩展点与接入 WebSocket 实时状态的建议方案,并给出从旧的 DOM 覆盖层组件迁移到画布内绘制的步骤与注意事项。
- 相关文件
- 画布渲染入口:
src/services/editor.service.ts
中drawPoint()
自定义绘制 - 库位网格绘制模块:
src/services/draw/storage-location-drawer.ts
(导出drawStorageGrid
) - 场景编辑页:
src/pages/scene-editor.vue
- WS 服务(示例/参考):
src/services/storage-location.service.ts
- 画布渲染入口:
一、渲染概览
- 使用 Meta2D 的自定义绘制回调,在
drawPoint()
内针对MapPointType.动作点
调用drawStorageGrid()
,在“世界坐标”中直接绘制 2x3 栅格。 - 这样,库位网格与点位同步缩放和平移,无需计算 DOM 偏移与容器滚动,也无需在模板中叠加覆盖层组件。
二、数据来源与字段约定
- 点位对象:
MapPen
(@api/map
导出的类型)。 - 动作点扩展字段:
pen.point.associatedStorageLocations: string[]
- 用于静态展示与数量溢出提示(+N)。
- 后续若接入 WS 实时状态,建议增加:
pen.point.storageStates?: Record<string, { occupied?: boolean; locked?: boolean; }>
- key 为库位层名(例如
layer_name
),value 为状态对象。
- key 为库位层名(例如
三、绘制模块 drawStorageGrid
路径:src/services/draw/storage-location-drawer.ts
签名:
export function drawStorageGrid(
ctx: CanvasRenderingContext2D,
pen: MapPen,
opts?: { fontFamily?: string },
): void
职责:
- 基于
pen.calculative.worldRect
决定栅格的尺寸、间距与摆放位置(点位右上角)。 - 前 5 格按默认样式绘制;若数量超出 6,则在最后一格显示
+N
。 - 采用“世界坐标”绘制,随 Meta2D 画布的缩放/平移自然同步。
可调参数(在代码内集中计算):
- 单格尺寸
cell
:约为点位较短边的 35%,限制在[6, 14]
(世界坐标单位)。 - 间距
gap
:约为点位较短边的 8%,限制在[2, 6]
。 - 圆角统一通过
roundedRectPath
构造路径,避免roundRect
类型兼容问题。
四、在 drawPoint()
中的接入
路径:src/services/editor.service.ts
核心片段:
// …计算文本等
ctx.fillText(label, x + w / 2, y - fontSize * lineHeight);
// 库位2x3栅格:动作点在画布上直接绘制(静态数据)
if (type === MapPointType.动作点) {
drawStorageGrid(ctx, pen, { fontFamily });
}
注意:需确保 EditorService.#register()
已注册 point 的自定义绘制函数(项目中已完成)。
五、接入 WS 实时状态(建议)
有两种模式可选:
-
模式 A:在
drawStorageGrid()
增加状态解析回调- 签名扩展:
opts.stateResolver?: (penId: string, layerName: string) => { occupied?: boolean; locked?: boolean; }
drawPoint()
调用时传入解析函数(从全局 Map 或服务读取),按状态填充不同的底色/边框/角标。- 优点:不污染
pen
数据,职责清晰;适合不同页面传入不同策略。
- 签名扩展:
-
模式 B:将状态写回
pen
上- WS 收到后更新
pen.point.storageStates[layer_name] = { … }
,然后editor.render()
触发重绘。 drawStorageGrid()
读取pen.point.storageStates
决定样式。- 优点:渲染模块无额外依赖;缺点:需管理好数据生命周期与清理。
- WS 收到后更新
建议优先使用模式 A,便于解耦与测试。
与 StorageLocationService
的对接
StorageLocationService.handleStorageLocationUpdate()
已按 operate_point_id
与站点名映射聚合库位数据:
- 可在服务层维护
Map<pointId, Map<layer_name, State>>
的结构。 drawPoint()
中调用drawStorageGrid(ctx, pen, { stateResolver })
,stateResolver
从该 Map 中读取。- 状态变化后调用
editor.render()
重绘即可生效。
六、样式与语义(可自定义)
- 默认颜色:
- 底板:
#00000022
(半透明) - 单格:
#f5f5f5
+#999
边框 - 溢出格:底
#e6f4ff
,边框#1677ff
,文字#1677ff
- 底板:
- 状态上色(建议):
- occupied=true:填充偏黄/橙(例:
#ffe58f
) - locked=true:边框高亮(例:
#fa541c
)或角标图标 - 冲突(同时 occupied & locked):设置优先级或组合样式
- occupied=true:填充偏黄/橙(例:
七、性能考量
- 绘制在同一 Canvas 渲染管线完成,没有额外 DOM 或布局成本。
- 仅当 WS 推送或交互(缩放/平移/选择)触发重绘,保持流畅。
- 如果点位非常密集,可在
drawStorageGrid
内做最小尺寸阈值,过小则不绘制或绘制为简化标记。
八、迁移步骤(从 DOM 覆盖层组件)
- 将组件
storage-location-grid-overlay.vue
从页面删除(如scene-editor.vue
)。 - 确认
drawPoint()
已导入并调用drawStorageGrid()
。 - 按需对接 WS:在服务层聚合状态,传入解析回调或写入
pen
。 - 验证缩放/平移/窗口尺寸变化场景,确保网格对齐与可读性。
九、测试清单
- 缩放到 0.5x、1x、2x 时,栅格位置与尺寸是否稳定且可读。
- 拖动画布及窗口 resize 后,栅格仍紧邻动作点右上角。
- 当
associatedStorageLocations.length
<= 6 与 > 6 时展示正确(含+N
)。 - 接入 WS 后:
- occupied/locked 状态能正确上色/标注。
- 状态切换时无残影,性能稳定。
十、常见问题 FAQ
-
Q:为何不再使用 DOM 覆盖层组件?
- A:避免坐标换算/偏移/滚动同步等复杂问题,统一交由 Meta2D 世界坐标与渲染管线处理。
-
Q:如果需要支持点击库位打开菜单?
- A:可在 Meta2D 的事件系统中命中该区域(保留格子范围),或保留一个轻量的浮层仅用于复杂交互(与绘制相互独立)。
-
Q:如何快速调整大小与颜色?
- A:修改
storage-location-drawer.ts
内的cell/gap
与颜色常量;如需主题化,可迁移到sTheme
。
- A:修改