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

6.0 KiB
Raw Blame History

库位渲染与状态集成说明

本文档说明当前项目中“库位网格”在 Meta2D 渲染链路中的实现方式、扩展点与接入 WebSocket 实时状态的建议方案,并给出从旧的 DOM 覆盖层组件迁移到画布内绘制的步骤与注意事项。

  • 相关文件
    • 画布渲染入口:src/services/editor.service.tsdrawPoint() 自定义绘制
    • 库位网格绘制模块: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_namevalue 为状态对象。

三、绘制模块 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 实时状态(建议)

有两种模式可选:

  • 模式 AdrawStorageGrid() 增加状态解析回调

    • 签名扩展: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