web-map/docs/库位渲染与状态集成说明.md

132 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 库位渲染与状态集成说明
本文档说明当前项目中“库位网格”在 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 为状态对象。
## 三、绘制模块 `drawStorageGrid`
路径:`src/services/draw/storage-location-drawer.ts`
签名:
```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`
核心片段:
```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` 决定样式。
- 优点:渲染模块无额外依赖;缺点:需管理好数据生命周期与清理。
建议优先使用模式 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设置优先级或组合样式
## 七、性能考量
- 绘制在同一 Canvas 渲染管线完成,没有额外 DOM 或布局成本。
- 仅当 WS 推送或交互(缩放/平移/选择)触发重绘,保持流畅。
- 如果点位非常密集,可在 `drawStorageGrid` 内做最小尺寸阈值,过小则不绘制或绘制为简化标记。
## 八、迁移步骤(从 DOM 覆盖层组件)
1. 将组件 `storage-location-grid-overlay.vue` 从页面删除(如 `scene-editor.vue`)。
2. 确认 `drawPoint()` 已导入并调用 `drawStorageGrid()`
3. 按需对接 WS在服务层聚合状态传入解析回调或写入 `pen`
4. 验证缩放/平移/窗口尺寸变化场景,确保网格对齐与可读性。
## 九、测试清单
- 缩放到 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`