Files
cmr-mini/doc/gameplay/准备页地图预览方案.md

7.2 KiB
Raw Permalink Blame History

准备页地图预览方案

文档版本v1.0 最后更新2026-04-07 12:18:00

本文档用于说明活动准备页的地图预览能力如何设计与落地。

当前目标不是直接进入实现,而是先把方案边界、分层、前后端职责和分阶段路径定清。


1. 目标

准备页当前已经具备:

  • 活动状态摘要
  • 赛道选择
  • 设备准备
  • 进入地图

但“本局对象预览”仍然主要是文字占位,对玩家帮助有限。

准备页地图预览的目标是:

  1. 在进入地图前,让玩家建立空间预期
  2. 在多赛道活动中,让玩家能直观看到当前赛道差异
  3. 让准备页更像“出发前准备”,而不是工程参数页
  4. 不打断当前 runtime 主链,也不额外制造一套重资源地图体系

2. 推荐方案

当前推荐采用:

低级别正式瓦片做底图,前端动态叠加赛道

也就是:

  • 底图来源:现有正式瓦片资源
  • 底图级别:选择一个较低 zoom 作为预览缩略底图
  • 叠加层:前端根据当前赛道数据在预览图上动态绘制起点、终点、控制点和腿线

这是一个“混合预览方案”:

  • 不单独制作新的预览地图资源
  • 不在前端完整拼装高精度交互地图
  • 只在准备页做只读预览

3. 为什么选这个方案

3.1 不新增独立地图资源

如果单独为准备页制作预览地图资源,会带来:

  • 资源重复
  • 发布链复杂度上升
  • 底图与正式地图不一致风险

使用低级别正式瓦片作为预览底图,可以保持:

  • 同源
  • 一致
  • 低成本

3.2 多赛道切换更自然

多赛道场景下:

  • 底图通常是同一张地图
  • 差异主要在赛道叠加层

因此最合理的方式是:

  • 底图固定
  • 切换赛道时仅重绘 overlay

这样:

  • 切换更快
  • 数据结构更清楚
  • 不需要为每个 variant 重新生成整张预览图

3.3 前后端职责清楚

后端负责:

  • 提供底图预览所需元数据
  • 提供赛道叠加所需坐标数据

前端负责:

  • 展示底图
  • 动态叠加赛道
  • 在准备页进行只读预览

这符合当前项目一直坚持的分层原则。


4. 整体分层

准备页地图预览建议分成 4 层。

4.1 地图底图层

来源:

  • 当前正式瓦片资源

形式:

  • 低级别缩略底图

职责:

  • 提供地点区域的空间背景

4.2 预览元数据层

来源:

  • 后端预览元数据

职责:

  • 告诉前端如何把经纬度投到预览图坐标系中

4.3 赛道叠加层

来源:

  • variant 控制点与腿线数据

职责:

  • 在准备页上画出当前赛道

4.4 准备页展示层

职责:

  • 只读展示
  • 切换赛道联动预览
  • 不承担局内交互

5. 后端需要提供的最小字段

V1 不要求后端提供完整预览图 URL而是先提供“底图元数据 + 赛道 overlay 元数据”。

建议后端提供以下最小结构:

{
  "preview": {
    "mode": "full",
    "baseTiles": {
      "tileBaseUrl": "https://.../tiles/",
      "zoom": 15,
      "tileSize": 256
    },
    "viewport": {
      "width": 800,
      "height": 450,
      "minLon": 117.0000,
      "minLat": 36.6000,
      "maxLon": 117.0800,
      "maxLat": 36.6600
    },
    "variants": [
      {
        "variantId": "variant_a",
        "name": "A线",
        "routeCode": "route-variant-a",
        "controls": [
          { "id": "start", "kind": "start", "lon": 117.01, "lat": 36.61 },
          { "id": "c1", "kind": "control", "lon": 117.02, "lat": 36.615 },
          { "id": "finish", "kind": "finish", "lon": 117.03, "lat": 36.62 }
        ],
        "legs": [
          { "from": "start", "to": "c1" },
          { "from": "c1", "to": "finish" }
        ]
      }
    ]
  }
}

其中关键字段是:

  • baseTiles.tileBaseUrl
  • baseTiles.zoom
  • viewport.width / height
  • viewport.minLon / minLat / maxLon / maxLat
  • variants[].controls
  • variants[].legs

这些字段足够前端做只读预览。


6. 前端如何消费

前端准备页的消费方式建议如下:

6.1 底图渲染

  • 使用低级别瓦片作为底图来源
  • viewportzoom 计算需要的瓦片范围
  • 只在准备页内绘制一张静态缩略底图

6.2 赛道叠加

  • 根据 viewport 把控制点经纬度投影到预览图坐标
  • 在 canvas 或同等绘制层上叠加:
    • 起点
    • 终点
    • 控制点
    • 腿线

6.3 多赛道切换

  • 切换赛道时不重新换底图
  • 只重绘叠加层

6.4 展示层级

准备页只做:

  • 只读预览
  • 不拖拽
  • 不缩放
  • 不交互打点

7. 多赛道场景如何处理

多赛道场景是这套方案的重点。

当前建议规则:

  1. 同一活动下,所有 variant 共用一张底图
  2. 当前选中的 variant 决定叠加层内容
  3. 如果活动允许手动选赛道,切换赛道时预览同步切换
  4. 如果活动是随机分配或后台指定:
    • 准备页在最终绑定前可只显示地点底图
    • 一旦后端返回最终绑定赛道,再显示该赛道 overlay

这套设计和当前多赛道 Variant 架构是一致的:

  • 底图属于地图对象
  • 叠加属于 variant 对象

8. 预览级别建议

建议预览能力分成 3 档:

8.1 none

  • 不显示地图预览
  • 只显示地点、地图、赛道文字信息

适用于:

  • 不允许赛前预览的正式比赛

8.2 summary

  • 显示底图
  • 只显示简化赛道范围、起终点或大致区域
  • 不暴露完整点位和腿线

适用于:

  • 需要局前空间感,但不允许完整剧透路线

8.3 full

  • 显示底图
  • 显示完整点位与腿线

适用于:

  • 体验活动
  • 教学活动
  • 低门槛公开活动

V1 建议先直接支持:

  • none
  • full

后面再补 summary


9. 分阶段实施建议

9.1 V1

只做:

  • 低级别瓦片底图
  • 前端动态赛道叠加
  • 支持多赛道切换联动
  • 只读展示

不做:

  • 复杂预览交互
  • 预览模式细分
  • 缩放与拖拽

9.2 V2

补:

  • none / summary / full
  • 不同活动类型的预览策略
  • 更细的赛道保密规则

9.3 V3

考虑扩展到:

  • 活动详情页缩略预览
  • 活动列表卡片缩略图
  • 赛后结果页路线回看缩略图

10. 不建议的方案

当前不建议:

10.1 单独制作一套预览地图资源

问题:

  • 成本高
  • 一致性差
  • 发布链复杂

10.2 前端直接现场拼完整高精度瓦片地图

问题:

  • 性能波动大
  • 首次加载慢
  • 多端一致性差

10.3 后端为每个 variant 预生成完整大图

问题:

  • 多赛道下资源重复
  • 每次改赛道都要重生图
  • 扩展性不如“底图固定 + 叠加切换”

11. 当前建议结论

准备页地图预览最推荐的路线是:

使用低级别正式瓦片作为预览底图,由前端在准备页动态叠加当前赛道。

这条路线的优点是:

  • 不新增独立地图资源
  • 底图与正式地图同源
  • 多赛道切换成本低
  • 前后端职责清晰
  • 易于分阶段落地

当前建议优先推进:

  1. 后端补预览元数据最小字段
  2. 前端在准备页实现只读底图 + overlay
  3. 先支持 full
  4. 后续再扩 summary / none