30-intro-gate-and-view-presets.md 6.9 KB

30: 进入系统的引导与视角预设(星球自转 + 点击进入 + 快速归位)

What to build: 进入 /cockpit 时先看到一个自转的星球与中央闪烁的「点击进入系统」提示;点击后镜头飞到目标城市(沅陵县 110.39028164, 28.44367870)的预设视角;进入后有一个按钮可随时一键归位到该视角。视角坐标与intro开关都由部署配置给,不硬编码在组件里。

(本票来自维护者 2026-09-17 反馈:「当前我完全找不到目标位置,无法判断 DEM 及精细影像是否成功部署」+ 明确要求自转星球/点击进入/归位按钮。原先没有任何票覆盖「进入系统的引导体验」与「命名视角预设」;票 03 只管三键输入契约,票 21 只管资源加载,故独立成票。)

Blocked by: 03, 21

Status: resolved Labels: ready-for-agent

请勿据标签重复接单:本票已完成并有关闭记录,Labels 保留只是为了让面板不把它退化成 needs-triage。

依赖与事实

  • 相机契约与引擎都已就绪:票 03(三键输入 + cameraControl)、票 21(地形/影像已接上)。
  • 地形感知的拾取是本票顺手做掉的前置动作:原先中心点走 pickEllipsoid(纯椭球,高程 0), 而沅陵县城地面高程一百多米起,所以拉近后相机会落进山体、画面全黑。本票: ① pickGroundAtCenter() 用 globe.getHeight 把拾取点抬到真实地表; ② 地形就绪后用 sampleTerrainMostDetailed 采样「家」视角的实测高程,写进预设。 实测:拉到距离下限 120 m 时中心高程 111.6 m(不再是 0),近景截图内容丰富(约 1 MB),不再黑屏。
  • 坐标口径:维护者给的 110.39028164, 28.44367870 是 CGCS2000 · 天地图坐标(与 WGS-84 在本项目精度下一致)。

验收

  • 进入 /cockpit 先看到自转的星球(不是静止球),且中央有闪烁的「点击进入系统」提示。
  • 点击后镜头飞到沅陵县预设视角(默认 110.39028164, 28.44367870,可被配置覆盖),落点与目标坐标一致(走查实测误差 1.4e-14°)。
  • 进入后有快速归位按钮(顶栏「归位」):平移/缩放后点它回到同一预设视角(中心、heading、pitch、range 都回;走查实测距离误差 0)。
  • 预设视角与 intro 开关由配置给(map.home / map.intro),组件里不硬编码坐标。
  • 引导层不影响既有验收:intro.enabled=false 可直接进系统(其它票走查用它自隔离);进入后外壳与地图行为不变。
  • 近景不黑屏:地形加载后拉到公里级/下限仍能看到地面(地形感知拾取生效)。
  • 有纯逻辑断言(verify/t30-view-presets.mjs)与真机走查记录(verify/t30-intro-walkthrough.mjs 7/7)。

进度:100%

已完成并关闭(2026-09-17)。 维护者「完全找不到目标位置、无法判断 DEM 与影像是否部署成功」的问题解决了: 进系统就是自转星球 + 点击进入 → 落到沅陵县城上空 12 km(县域级),顶栏「归位」随时回到该视角。

改动

  • 新增 domain/viewPresets.js(纯函数):planHome() / planIntro() 计划层、homeLabel() 文案、isAtHome() 归位判定(含容差与 heading 环绕)。
  • 新增 components/CockpitIntro.vue:全屏引导层(点击/Enter/Space 进入、闪烁文案、prefers-reduced-motion 时不动画)。
  • services/cameraControl.js:新增 applyViewPreset(pivot, hpr, { immediate }) —— 整段视角(中心 + heading/pitch/range)一次到位,与票 03 的 setFocus()(只换中心、保持距离)区分开。
  • services/mapService.js:getHomeView() / goHome() / atHome() / setGlobeSpin();自转与飞行互斥(飞行前先 stopSpin() 并置 spinPaused,否则自转每帧 immediate 写中心会把飞行目标冲掉 —— 实测踩过);getLifecycleStats() 增 spin。
  • services/cesiumEngine.js:pickGroundAtCenter() 改为地形感知(globe.getHeight);新增 sampleTerrainHeight()(sampleTerrainMostDetailed)。
  • services/cockpitConfig.js:map.home{lon,lat,height,heading,pitch,range,label} 与 map.intro{enabled,title,subtitle,spinSeconds} 的归一化与校验。
  • CockpitShell.vue:引导层挂载 + 顶栏「归位」按钮(data-home-at 供走查)+ 进入/归位都要等引擎就绪(重试到相机接上)。
  • public/cockpit/config.json:本机配置补上 home(沅陵 110.39028164, 28.4436787,pitch -55,range 12 km)与 intro;config.example.json 同步补该两节与说明。

验证证据(yarn dev @ 8001,Chrome 152 headless)

  • 纯逻辑 t30-view-presets.mjs:通过(默认值、归一化含三处错字段 issue、预设解析、homeLabel 文案、归位判定含 heading 360≡0 与「无相机状态」、并与本机配置的沅陵坐标对齐核对)。
  • 真机走查 t30-intro-walkthrough.mjs → 7/7:引导层在位且闪烁动画生效(animationName 非 none);星球确实在自转(2.6 s 内中心经度 Δ≈-19.6°);点击后引导消失且镜头落在沅陵(Δlon 1.4e-14°,Δlat 0,range 12 km);进入后自转停止(2 s 内零漂移);手动平移+缩放推离后按钮显示未在家,点「归位」回到同一视角(中心误差 1.4e-14°、距离误差 0)且按钮显示已在家;全程无页面级报错。
  • 视觉:引导页(自转星球 + 「点击进入系统」)与进入后(沅陵县城 12 km,河道/桥/地形起伏,顶栏有「归位」)。
  • 近景回归:拉到距离下限 120 m 时中心高程 111.6 m(地形感知生效),近景截图约 1 MB(内容非纯黑)。 —— 注:先前用 drawImage(canvas) 读回判定「黑屏」是测错了:WebGL 默认 preserveDrawingBuffer:false, 读回永远全黑;改用 CDP 截图判定。
  • 回归:t01 走查 20/20、t04 9/9、t29 6/6、t21 9/9、t28 7/7; 8 个逻辑脚本(t01/t03/t04/t06/t21/t28/t29/t30)全通过;yarn build exit 0。
  • 兼容处理:票 30 起 /cockpit 默认有引导层(z-index 20,进入前挡住交互),所以 t01 与 t21 的走查 显式注入 intro:{enabled:false}(它们是测「进入之后」的行为)——这是配置开关的正当用法,不是绕过断言。

遗留

  • 引导层目前是每次进入 /cockpit 都显示(刷新即重生)。要不要"记住已进入"(localStorage)由维护者定; 加的话是一行判断,但会影响走查的可重复性,故未擅自加。
  • 「自转」是绕地轴推进中心经度实现的(因为 cameraControl 每帧 lookAtTransform 会覆盖直接转相机); 观感是星球自转,但严格说转的是相机。若将来要真正的"地球自转"(经纬网动、相机不动),需另立票。