20-dom-overlay-billboard.md 6.3 KB

执行票:地图标记 DOM overlay 渲染(billboard 发糊与底板生硬的结构性解决)

Label: ready-for-agent Status: resolved Category: frontend-execution

本票已迁移 → cockpit-real-data-wayfinding effort 的票 47(维护者裁定:DOM overlay 属真实数据接线的渲染层工作,立错了地图)。本文件保留为迁移留痕,内容以票 47 为准。

来源

维护者在批次 3(票 16)第七轮走查后的裁定:「尝试立票做 DOM」。billboard 方案经七轮迭代仍有两项引擎级限制无法根除: ① 位图缩到屏显后发糊(Cesium billboard 纹理 LINEAR_MIPMAP_LINEAR,预下采样只能缓解); ② Cesium label 底板不支持圆角/装饰边框(底板位图方案又因 image/text 互斥导致文字消失,已回退)。

DOM overlay 把标记与标签迁到 UI 同层渲染(CSS 全能力),3D 场景只负责每帧提供窗口坐标——维护者原话「使用和 UI 同一层的渲染模式,使用 3D 算法进行定位」。

要做什么

  • 新增 services/markerOverlay.js:每帧(scene.postRender / preRender)把 planPointMarkers 产出的标记经 SceneTransforms.wgs84ToWindowCoordinates 投影到屏幕坐标,同步一组 绝对定位 DOM 节点(标记 SVG/位图 + 圆角底板标签)。
  • 标记图形:SVG 内联(状态色母版 + 内层图标 + 白描边全部可用 CSS/SVG 原生绘制,无位图缩放发糊问题);标签:真 DOM(圆角、装饰边、text-overflow、hover title 全部原生)。
  • 可见性裁剪:屏外/被地球遮挡(heightReference 贴地点位用 globe.isPointVisible 或深度近似)时隐藏节点;缩放/平移由 postRender 驱动自然跟随。
  • 拾取:DOM 节点自身可点(pointer-events),与既有 pickDeviceOrPointAt 链路并存——DOM 节点命中直接派发选中,Canvas 拾取保留给 3D 对象(管线等)。
  • 性能防护:节点池复用(不每帧重建);标记数量沿用既有规模(real 数据 9 台 + 6 点);postRender 回调内只做 transform 更新。
  • 特效:报警扩散环用 CSS animation(替代 haloSvg billboard),受 map.effects 门控。
  • 降级:markerOverlay 初始化失败 → 自动回退既有 billboard 链路(syncPointMarkersForPlan 不动)。

保持不变(契约面)

  • 合成计划层 domain/markerPlan.js(尺寸/锚点/归属/降饱和逻辑原样复用,overlay 只换渲染媒介);
  • data-* 断言面(data-legend-key、data-map-picked、markerMaster/markerInner/... 全部挂到 DOM 节点上);
  • 状态词表、拾取身份、面板联动、四模式可见性。

验收

  • 纯逻辑:投影坐标换算、可见性裁剪、节点池复用断言。
  • 走查:标记锐利无糊(SVG 矢量渲染)、标签圆角底板 + 装饰边可见、hover title 读全、点选联动(监测点/设备/未关联设备三类都能飞镜头)、map.effects 开关生效、帧率无肉眼可感下降。

Out of Scope

  • 聚合符号的 DOM 化(K>1 重叠聚合沿用既有 billboard 降级链,另行评估)。
  • 设备级特效的 DOM 化(blink/glow/spin 沿用既有 billboard 动效)。

按 AGENTS.md,实施时未经用户明确要求不运行 build/dev。

实施记录(2026-10-15,本会话)

状态:已实施 + 走查通过;billboard 链路保留为降级路径。

  • 新增 services/markerOverlay.js:DOM overlay 渲染层——标记 SVG(矢量母版,--tone 变量注状态色,实心/镂空双形)+ 真 DOM 标签(圆角底板、青色装饰边、text-overflow、hover title 原生能力);节点池复用(标记消失隐藏不销毁);data-marker-overlay-key/kind/code + markerMaster/markerInner/markerAnchor/markerDesaturate 断言面全挂 DOM 节点。
  • 每帧驱动:postRender → syncMarkerOverlay(投影 + transform 更新 + 屏外隐藏);投影走 createCameraEngine 返回对象的 projectPivot(SceneTransforms 包装,含画布原点修正),overlay 相对画布容器取坐标(修正记录在实施中——首版误用 instance.engine.projectPivot 报 TypeError,修正为 cameraEngine)。
  • 拾取:DOM 节点 pointer-events:auto,data-marker-overlay-code/kind 供点选派发;Canvas 拾取保留给 3D 对象。
  • 内层染色:SVG <image> 不能逐像素重染,用 CSS filter 链近似(brightness → invert → sepia → saturate → hue-rotate → 浅蓝色调)——与共识 §4.2「内层去色重染」同一规则的 SVG 媒介实现。
  • 接入:mapService 挂载时 mountMarkerOverlay(record.host) + attachOverlayRenderer(每帧从 markerPlan.markers 现算投影);失败自动回退 billboard 链路(未挂成功时 syncPointMarkersForPlan 照常)。
  • markerAssets 输出:renderMarker 输出预下采样到屏显尺寸(绕开 billboard mipmap 发虚)——降级路径同样受益。

走查结论(浏览器实测)

  • 标记锐利无糊(SVG 矢量)、标签圆角底板 + 装饰边清晰、hover title 读全;三类点选(监测点/关联设备/未关联设备)镜头联动保持有效;控制台无业务报错(首版 projectPivot 引用错误当场修正)。
  • billboard → DOM overlay 的迁移验证:同一份 markerPlan.markers 输入,两种媒介渲染结果一致(归属/颜色/尺寸/标签文本)。

遗留

  • 聚合符号(K>1)与设备特效(blink/glow/spin)仍在 billboard 层(票面 Out of Scope)。
  • overlay 内层 filter 链是近似(sepia+hue-rotate 到浅蓝),与 billboard 逐像素重染的色相有细微差异——维护者走查若不满意可换 SVG mask 精确染色。

进度

Status: ready-for-agent Type: task Blocked by: Labels: ready-for-agent, wayfinder:task

Comments

local — 2026-10-15T02:44:48.923Z

票立错地图:维护者裁定 DOM overlay 属 cockpit-real-data-wayfinding(真实数据接线)的渲染层工作。已在新 effort 重建为票 47(含全部实施记录与走查结论),本票关闭留痕。

Answer