480 lines
23 KiB
Markdown
480 lines
23 KiB
Markdown
# 地图模块 3D Cesium 实施计划
|
||
|
||
## 1. 目标
|
||
|
||
在现有地图体系下补齐 `3D(Cesium)` 视图能力,使其尽量复用 `2D(OpenLayers)` 的业务编排结果,满足以下要求:
|
||
|
||
- 3D 默认进入中国视角,不再落到美国区域。
|
||
- 3D 初始化时显示过渡动画,再定位到中国。
|
||
- 3D 保留基础底图加载能力,但不提供底图切换面板。
|
||
- 3D 支持锚点展示。
|
||
- 3D 支持与 2D 一致的鼠标悬停 popup,样式复用现有 popup。
|
||
- 3D 支持与 2D 一致的锚点点击行为,点击后打开同一套详情弹框逻辑。
|
||
- 菜单切换、图层树勾选、图例勾选后,3D 锚点与 2D 一样联动变化。
|
||
- 3D 必须复用 `eng_point` 的层级显示规则,中型水电站仅在 `ENG_POINT_MEDIUM_VISIBLE_ZOOM = 7.5` 以上显示。
|
||
|
||
## 2. 2D 现状梳理
|
||
|
||
当前 `2D` 的能力并不是散落在页面里,而是已经形成了比较清晰的分层:
|
||
|
||
### 2.1 页面入口
|
||
|
||
- `src/components/gis/GisView.vue`
|
||
- 负责挂载地图容器、popup 容器、地图控制器、图例、图层树。
|
||
- 页面只调用 `mapOrchestrator.mountView()` 和 `handlePageChange()`,不直接拼地图业务。
|
||
|
||
### 2.2 地图编排层
|
||
|
||
- `src/modules/map/application/map-orchestrator.ts`
|
||
- 负责页面初始化、菜单切换、图层配置加载、图例配置加载、基地切换、缩放联动。
|
||
- 2D/3D 都应尽量复用这一层,避免在 Cesium 侧另起一套业务流程。
|
||
|
||
### 2.3 地图统一门面
|
||
|
||
- `src/components/gis/map.class.ts`
|
||
- 对外暴露统一接口,如:
|
||
- `addBaseDataLayer`
|
||
- `addInitDataLayer`
|
||
- `mdLayerTreeShowOrHidden`
|
||
- `setLegendPointVisible`
|
||
- `controlBaseLayerTreeShowAndHidden`
|
||
- `initPopupOverlay`
|
||
- `flyTopanto`
|
||
- 业务层只认这套接口,不应感知底层是 `OpenLayers` 还是 `Cesium`。
|
||
|
||
### 2.4 2D 地图能力落点
|
||
|
||
- `src/components/gis/map.ol.ts`
|
||
- 已实现的关键能力:
|
||
- 默认中国视角初始化
|
||
- 基础底图加载与切换
|
||
- 点位图层注册和显隐
|
||
- 图例控制单类锚点显隐
|
||
- 鼠标 hover popup
|
||
- click 打开详情弹窗
|
||
- 基地裁切与底图遮罩
|
||
- 缩放/移动后的批量 popup 和标签刷新
|
||
|
||
### 2.5 2D 锚点与 popup 支撑
|
||
|
||
- `src/components/gis/ol/point-layer-manager.ts`
|
||
- 负责将点位数据转成地图要素、分层、索引、图例显隐。
|
||
- `src/components/gis/ol/popup-manager.ts`
|
||
- 负责 hover 命中、popup DOM 内容复用、批量 popup。
|
||
|
||
### 2.6 图层树和图例交互
|
||
|
||
- `src/components/mapController/LayerController.vue`
|
||
- 图层树勾选后走 `mapOrchestrator.applyLayerSelection()`
|
||
- `src/components/mapLegend/index.vue`
|
||
- 图例点击后走 `mapOrchestrator.toggleLegend()` / `toggleLegendBatch()`
|
||
- `src/store/modules/map.ts`
|
||
- 真正把缓存数据、图层状态、图例状态应用到地图实例
|
||
- 也就是说,`3D` 只要把统一接口补齐,就能直接接住现有业务流
|
||
|
||
### 2.7 2D 已有特殊业务规则
|
||
|
||
- 锚点点击逻辑已在 `src/components/gis/map.ol.ts` 实现:
|
||
- 命中锚点后,`ylfb` 走 `ylfbModalVisible`
|
||
- 其他锚点走 `modalVisible`
|
||
- 标题和参数都直接取当前锚点数据
|
||
- `eng_point` 的中型水电站显示阈值已在现有链路中实现:
|
||
- 阈值常量位于 `src/modules/map/application/map-orchestrator.ts`
|
||
- 过滤逻辑位于 `src/store/modules/map.ts` 的 `filterPointLayerDataForDisplay()`
|
||
- `3D` 不应重新发明一套规则,而应复用这套现有过滤结果
|
||
- 部分点位会随着缩放级别提升显示得更多,不是简单的“图层开/关”:
|
||
- `eng_point` 的中型电站要到 `ENG_POINT_MEDIUM_VISIBLE_ZOOM = 7.5` 以上才显示
|
||
- 水电开发页在缩放跨过 `12` 级时会自动补开一批动态图层
|
||
- `2D` 内部还存在点位密度阈值、近邻点展开、批量 popup 阈值等缩放联动规则
|
||
- `2D` 对锚点存在碰撞检测与密度控制,不是所有点始终全量显示:
|
||
- 图标和标签会分别经过碰撞计算
|
||
- 低缩放下会因为密度、碰撞、区域裁切、图例状态而隐藏部分点
|
||
- 高缩放下会逐步放开限制,显示更多锚点和标签
|
||
|
||
## 3. 3D 当前现状与缺口
|
||
|
||
### 3.1 已有内容
|
||
|
||
- `src/components/gis/map.cesium.ts`
|
||
- 当前只完成了最小化 `Cesium.Viewer` 初始化。
|
||
- 已有基础缩放、截图、`flyTopanto()` 雏形。
|
||
|
||
### 3.2 当前主要缺口
|
||
|
||
- `init()` 里虽然定义了 `flyToChina()`,但没有真正执行,也没有 `resolve(viewer)`,初始化流程不完整。
|
||
- 默认底图仍是 ArcGIS 全球影像,因此启动时容易落到美国默认视角。
|
||
- `addBaseDataLayer()` 为空,无法接住当前 `GISMap/customBaseLayer` 逻辑。
|
||
- `addInitDataLayer()` 为空,无法展示锚点。
|
||
- `mdLayerTreeShowOrHidden()` 为空,菜单切换时 3D 锚点不会同步显隐。
|
||
- `setLegendPointVisible()` 为空,图例勾选不会影响 3D 锚点。
|
||
- `initPopupOverlay()` 为空,无法复用 2D popup 容器。
|
||
- 缺少点击命中与详情弹框联动,3D 当前无法做到“点击锚点与 2D 同行为”。
|
||
- `controlBaseLayerTreeShowAndHidden()` 为空,3D 基础底图和叠加层无法受现有图层树控制。
|
||
- 尚未验证 `eng_point` 的缩放阈值规则在 3D 下是否能完全复用,存在实现时遗漏中型站点显隐的风险。
|
||
- 目前没有承接 `2D` 中“放大到具体层级显示更多锚点”的缩放联动显示机制。
|
||
- 目前没有承接 `2D` 中图标/标签的碰撞检测逻辑,后续若直接全量渲染,视觉效果会与 `2D` 明显不一致。
|
||
- 当前没有建立 `Cesium entity / datasource / imageryLayer` 的注册表,后续联动无从下手。
|
||
|
||
## 4. 实施原则
|
||
|
||
- 不重做业务编排,优先复用 `map-orchestrator.ts` 和 `src/store/modules/map.ts`。
|
||
- 不额外引入一套 3D 专用图例和图层状态,仍以现有 store 为唯一运行态来源。
|
||
- 不单独复制 `eng_point` 的中型站显示规则,优先复用现有 `mapStore` 过滤结果。
|
||
- 不单独新建一套点击弹框协议,优先保持与 `map.ol.ts` 相同的命中后行为。
|
||
- 对“缩放越大显示越多锚点”这类规则,优先复用现有缩放阈值与显示门闩,不做拍脑袋的新规则。
|
||
- 对碰撞检测,优先与 `2D` 保持同方向行为:低缩放控量,高缩放放开,而不是 3D 全量堆点。
|
||
- 先做最小闭环,再逐步补能力:
|
||
- 第一步保证 3D 能正确初始化并定位中国。
|
||
- 第二步保证基础底图能显示。
|
||
- 第三步保证锚点能显示。
|
||
- 第四步保证 popup、图层树、图例联动打通。
|
||
- 3D 不做“基础地图切换 UI”,但底层仍要支持 `customBaseLayer + addBaseDataLayer(..., true)` 这一逻辑。
|
||
|
||
## 5. 分步骤实施计划
|
||
|
||
### Step 1:修正 3D 初始化并默认定位中国 ✅️
|
||
|
||
目标:
|
||
|
||
- 切到 3D 后稳定初始化 viewer。
|
||
- 首屏出现一个轻量加载动画。
|
||
- 初始化完成后飞到中国默认视角。
|
||
|
||
计划:
|
||
|
||
- 修复 `map.cesium.ts` 的 `init()`:
|
||
- 保证初始化后一定 `resolve(this.viewer)`。
|
||
- 执行 `flyToChina()`。
|
||
- 补一个可控的启动过渡动画。
|
||
- 统一中国默认参数:
|
||
- 中心经纬度建议复用 `104.5, 36.5`
|
||
- 相机高度先按全国视角收口,后续再微调
|
||
- 如果切回 2D 再切到 3D,仍然要能正确重建 viewer。
|
||
|
||
验收:
|
||
|
||
- 点击 `3D` 按钮后,不再出现美国默认视角。
|
||
- 首屏有加载过渡。
|
||
- 进入后稳定落在中国。
|
||
|
||
### Step 2:展示 3D 基础底图 ✅️
|
||
|
||
目标:
|
||
|
||
- 3D 不显示空球。
|
||
- 保留“基础底图 + 3D 专用底图地址”能力。
|
||
- 不提供底图切换面板,但底层能吃现有配置。
|
||
|
||
计划:
|
||
|
||
- 在 `MapCesium` 内建立基础图层注册表。
|
||
- 实现 `addBaseDataLayer(layer, isShow)`:
|
||
- 对 `customBaseLayer` 使用 `url_3d`
|
||
- 对 `BASEMAP-img`、`BASEMAP-white` 预留兼容能力
|
||
- **必须处理 `wmts` 类型图层**:2D 通过 `WMTS` source 加载,3D 使用 `Cesium.WebMapTileServiceImageryProvider`,从 URL 参数中提取 LAYER/TILEMATRIXSET
|
||
- **必须提供 `tileMatrixLabels`**:Cesium 默认用纯数字作为 tileMatrix 参数值,但本系统 WMTS 服务器要求 `TileMatrixSet:zoom` 格式(如 `EPSG:3857_hbb_zrbhq_l13:4`)。需构建 `["TileMatrixSet:0", "TileMatrixSet:1", ...]` 传入 `tileMatrixLabels`。
|
||
- 其他类型:`raster-dem`→XYZ、MapServer→ArcGIS、其余 →WMS
|
||
- **注意**:还存在一个 `key = "powerBaseStation"` 的基地底图图层,该图层**初始化时不加载**(已在 `IGNORED_BASE_LAYER_KEYS` 中忽略),但后续可通过图层树手动勾选显示。
|
||
- 实现 `controlBaseLayerTreeShowAndHidden()`:
|
||
- 让图层树勾选能控制 3D 底图显隐
|
||
- 根据你的要求,UI 层先不开放 `BaseLayerSwitcher` 的 3D 切换行为,只保留默认基础底图加载。
|
||
|
||
验收:
|
||
|
||
- 切到 3D 后可稳定看到基础底图。
|
||
- 图层初始化时 `addBaseDataLayer(this.baseLayerConfig, checked, true)` 的思路在 3D 可落地。
|
||
|
||
### Step 3:打通 3D 锚点展示 ✅️
|
||
|
||
目标:
|
||
|
||
- 3D 能展示和 2D 同源的锚点数据。
|
||
- 菜单切换后,3D 能跟随页面数据切换。
|
||
|
||
计划:
|
||
|
||
- 在 `MapCesium` 内建立点位图层注册结构,按 `layerKey -> entity[]` 管理。
|
||
- 实现 `addInitDataLayer(pointData, layerType)`:
|
||
- 复用当前点位数据结构
|
||
- 解析 `lgtd/lttd/iconCode/titleName/stnm/anchoPointState/popupHtml`
|
||
- 复用现有图标资源路径
|
||
- Entity ID 使用 `${layerKey}:${item._id || `${iconType || 'point'}_${stcd}`}`,与 2D 对齐,确保同 stcd 不同 sttpMap 的点不被覆盖
|
||
- 确保 `eng_point` 仍按现有 `mapStore` 过滤后的数据展示,中型站点只在 `7.5` 以上层级出现
|
||
- 为后续缩放驱动的增量显示预留运行态字段(`_legendVisible`、`_regionVisible`、`_densityVisible`),不把所有点简单一次性硬渲染
|
||
- 实现 `mdLayerTreeShowOrHidden(layerType, checked)`:
|
||
- 图层树控制整个点图层显隐
|
||
- 实现 `removePointLayer()` / `hasLayer()`
|
||
- 便于后续页面切换和重载
|
||
|
||
验收:
|
||
|
||
- 切到 3D 后当前页默认勾选图层的锚点能显示。
|
||
- 切换菜单后,3D 锚点跟随变化。
|
||
- 取消勾选图层后,对应锚点消失。
|
||
- `eng_point` 在低于 `7.5` 时不显示中型水电站,高于 `7.5` 时正常显示。
|
||
|
||
### Step 4:打通 3D 基地裁切(jdPanelControlShowAndHidden) ✅️
|
||
|
||
目标:
|
||
|
||
- 3D 点击基地面板后,与 2D 行为一致。
|
||
- 加载基地边界 GeoJSON,只显示区域内锚点,隐藏区域外锚点。
|
||
- 取消基地时恢复显示所有锚点。
|
||
|
||
计划:
|
||
|
||
- 在 `MapCesium` 中捕获 `hydropBase` 配置,与 2D 一样在 `addBaseDataLayer` 中记录。
|
||
- 实现 `jdPanelControlShowAndHidden(baseid, isAll)`:
|
||
- `isAll=false`:清除 3D 球面遮罩实体、恢复所有锚点区域可见性、清除裁切状态。
|
||
- `isAll=true`:先隐藏所有锚点,异步加载基地边界 GeoJSON,执行点在面判断后仅显示区域内锚点,同时在球面绘制裁切边界多边形(`applyRegionMask`),最后飞行到区域视野。
|
||
- 在 `createEntityPropertiesBag` 中新增 `_regionVisible` 属性,初始为 `true`。
|
||
- 在 `applyPointVisibilityRefresh` 中跳过 `_regionVisible !== false` 的实体,确保裁切后碰撞检测不会把区域外锚点重新显示出来。
|
||
- 复用 `extractPolygonCoords` / `isPointInRing` 射线法判断逻辑(与 `region-mask-manager.ts` 一致)。
|
||
- 支持 `AbortController` 取消前一次未完成的请求,避免响应顺序错乱。
|
||
- `applyRegionMask` 将 GeoJSON 多边形转换为 Cesium `PolygonHierarchy`,在球面绘制半透明填充 + 可见边界的区域多边形,模拟 2D 底图 Canvas 裁切遮罩的视觉效果。
|
||
|
||
验收:
|
||
|
||
- 点击基地后,3D 只显示该基地区域内的锚点,区域外锚点隐藏。
|
||
- 取消基地后,所有锚点恢复正常显示。
|
||
- 快速切换基地不会出现旧数据覆盖新数据的问题。
|
||
- 多次切换 2D/3D 后基地裁切行为正常。
|
||
|
||
### Step 5:打通 3D popup 与 hover ✅️
|
||
|
||
目标:
|
||
|
||
- 3D 鼠标悬停时显示与 2D 一样的 popup。
|
||
- popup 样式复用现有 DOM 和样式,不再单独做一版。
|
||
|
||
计划:
|
||
|
||
- 实现 `initPopupOverlay(popupContainer)`
|
||
- 继续复用 `GisView.vue` 中现有 popup 容器
|
||
- 在 Cesium 中增加鼠标移动命中:
|
||
- 基于 `ScreenSpaceEventHandler`
|
||
- hover 到锚点时读取 entity 附带属性
|
||
- popup 内容生成逻辑复用 2D 现有字段:
|
||
- 优先使用 `popupHtml`
|
||
- 否则走通用字段渲染
|
||
- 处理离开锚点时隐藏 popup。
|
||
|
||
验收:
|
||
|
||
- 鼠标移入锚点出现 popup。
|
||
- 样式和 2D 保持一致。
|
||
- 移出后 popup 正常消失。
|
||
|
||
### Step 6:补齐缩放驱动显示与碰撞检测
|
||
|
||
目标:
|
||
|
||
- 3D 在低缩放下控制锚点数量,避免全量堆叠。
|
||
- 3D 在放大到具体层级后,逐步显示更多锚点。
|
||
- 3D 的图标/标签显示效果尽量接近 2D,不出现严重遮挡。
|
||
|
||
计划:
|
||
|
||
- 先承接现有明确可复用的缩放规则:
|
||
- `eng_point` 的 `7.5` 阈值
|
||
- 水电开发页的 `12` 级动态图层联动
|
||
- 再补 3D 侧的显示门闩:
|
||
- 低缩放下根据缩放级别、图层状态、图例状态控制 entity 显隐
|
||
- 高缩放下逐步放开限制,显示更多锚点
|
||
- 为 3D 补一版轻量碰撞控制:
|
||
- 至少先控制标签碰撞,避免名称完全叠在一起
|
||
- 如有必要,再补图标级碰撞或屏幕网格抽稀
|
||
- 明确与 2D 对齐的目标不是“算法完全一样”,而是“视觉行为一致”:
|
||
- 低缩放控量
|
||
- 高缩放增量显示
|
||
- 关键锚点不被完全淹没
|
||
|
||
验收:
|
||
|
||
- 3D 在全国视角下不会一次性挤满所有锚点。
|
||
- 放大到具体层级后会看到更多锚点逐步出现。
|
||
- 标签和锚点不会大面积重叠到不可读。
|
||
|
||
### Step 7:打通 3D 锚点点击详情 ✅️
|
||
|
||
目标:
|
||
|
||
- 3D 点击锚点后,行为与 2D 一致。
|
||
- 继续复用现有详情弹框状态和参数结构。
|
||
|
||
计划:
|
||
|
||
- 在 Cesium 中增加点击命中:
|
||
- 基于 `ScreenSpaceEventHandler`
|
||
- 命中锚点后读取 entity 绑定的原始业务数据
|
||
- 复用 `2D` 当前点击行为:
|
||
- `sttpMap === 'ylfb'` 时打开 `ylfbModalVisible`
|
||
- 其他锚点打开 `modalVisible`
|
||
- `params`、`title` 赋值逻辑与 `map.ol.ts` 保持一致
|
||
- 避免 hover popup 与 click 弹框互相干扰。
|
||
|
||
验收:
|
||
|
||
- 点击 3D 锚点后可打开与 2D 一致的详情弹框。
|
||
- `ylfb` 和普通锚点分支行为一致。
|
||
- 点击空白区域不会误触发弹框。
|
||
|
||
### Step 8:打通图例联动 ✅️
|
||
|
||
目标:
|
||
|
||
- 图例勾选后,3D 只显示对应状态的锚点。
|
||
|
||
计划:
|
||
|
||
- 实现 `setLegendPointVisible(layerKey, anchoPointState, checked)`:
|
||
- 复用 `anchoPointState` 作为图例匹配字段
|
||
- entity 级别维护显示状态
|
||
- 如果后续需要,也可补一个 3D 版本的图例索引表,避免每次全量遍历。
|
||
|
||
验收:
|
||
|
||
- 图例单项勾选/取消时,3D 对应类别锚点同步显隐。
|
||
- 图例分组勾选/取消时,3D 行为与 2D 保持一致。
|
||
|
||
### Step 9:补足收口与稳定性 ✅️
|
||
|
||
目标:
|
||
|
||
- 让 3D 能稳定参与现有地图生命周期。
|
||
|
||
计划:
|
||
|
||
- 清理 Cesium 事件监听、viewer、entity、datasource,避免重复切换内存泄漏。
|
||
- 检查 `switchView('2D' | '3D')` 前后 popup、底图、图层注册是否被正确重置。
|
||
- 检查 hover、click、图例、图层树、缩放阈值这几条联动链路在 3D 是否完全闭环。
|
||
- 视情况补最小诊断日志,确认菜单切换与图层联动没有漏项。
|
||
|
||
验收:
|
||
|
||
- 2D/3D 多次来回切换不报错。
|
||
- 菜单切换、图层切换、图例切换行为稳定。
|
||
|
||
## 6. 推荐落地顺序
|
||
|
||
按你的要求,建议严格按下面顺序推进:
|
||
|
||
1. 默认定位到中国 + 启动动画
|
||
2. 展示基础底图
|
||
3. 展示锚点 3.5. 补基地裁切(jdPanelControlShowAndHidden)
|
||
4. 补 hover popup
|
||
5. 补缩放驱动显示与碰撞检测
|
||
6. 补锚点点击详情
|
||
7. 补图层树联动
|
||
8. 补图例联动
|
||
9. 做切换稳定性收口
|
||
|
||
## 7. 预计修改文件
|
||
|
||
- `src/components/gis/map.cesium.ts`
|
||
- 3D 地图主体实现,主改动文件
|
||
- `src/components/gis/map.class.ts`
|
||
- 视情况补齐 2D/3D 切换后 popup 初始化和服务切换细节
|
||
- `src/components/gis/GisView.vue`
|
||
- 视情况控制 3D 下的底图切换器显示策略、加载态挂载位置
|
||
- `src/components/mapController/index.vue`
|
||
- 若需要补 3D 初始化后的交互控制
|
||
|
||
## 8. 当前建议
|
||
|
||
建议先只做 `Step 1`,也就是:
|
||
|
||
- 修正 Cesium 初始化完成逻辑
|
||
- 增加 3D 启动加载动画
|
||
- 默认飞到中国
|
||
|
||
这一步最小、最容易验证,也能先把“打开 3D 看起来不对”的核心问题解决掉。
|
||
|
||
## 9. 必须补齐的隐藏逻辑清单
|
||
|
||
下面这些逻辑不是表面接口能直接看出来的,但如果 `3D` 不补,最终效果就会和 `2D` 明显不一致。
|
||
|
||
### 9.1 图层与菜单切换 ✅️
|
||
|
||
- ✅ 菜单切换时,只隐藏旧页点图层,不隐藏底图。(编排器 `handlePageChange` 控制,Cesium 被动接收数据)
|
||
- ✅ 图层树勾选前要先经过互斥规则归一化:(store 层 `updateLayerData` 处理,Cesium 不感知)
|
||
- `rare_fish_point` 与 `fish_along_point` 互斥
|
||
- `stinfo/stinfo_video_point` 与 `stinfo_ai_video_point` 互斥
|
||
- `facilities` 与 `facilities_built` 两个分支互斥
|
||
- ✅ 点图层取消勾选时只隐藏,不删除缓存;重新勾选时优先从缓存恢复。`mdLayerTreeShowOrHidden` 设置 `_layerVisible` 标志,不删除 `pointLayerRegistry` 条目。
|
||
- ✅ **图层树勾选时按 `type` 字段走不同分支**(见 `updateLayerData`,store 层处理):
|
||
- `type === 'pointMap'` → 走 `handlePointMapLayer` → 调用 `mdLayerTreeShowOrHidden`(已实现,L1624)
|
||
- `type === 'GISMap'` → 走 `controlBaseLayerTreeShowAndHidden`(已实现,L1345)
|
||
- 3D Cesium 已同时实现这两个方法。
|
||
|
||
### 9.2 图例与点内显隐 ✅️
|
||
|
||
- ✅ 图例控制的是图层内部锚点是否可见,不是图层本身是否可见。`setLegendPointVisible` 使用 `_legendVisible` 标志,与 `_layerVisible` 独立。
|
||
- ✅ 图层恢复显示时,图例要先整层全关,再按当前 checked 状态逐项恢复。支持 `anchoPointState=''` 全关 → 逐项 `(state, true)` 恢复两步模式(L1764-1787)。
|
||
- ✅ 环保设施图例组当前是只展示不交互。(编排器层面控制,Cesium 不感知)
|
||
|
||
### 9.3 缩放驱动显示 ✅️
|
||
|
||
- ✅ `eng_point` 的中型水电站只在 `ENG_POINT_MEDIUM_VISIBLE_ZOOM = 7.5` 以上显示。(store `filterPointLayerDataForDisplay` 在数据进入 Cesium 前过滤)
|
||
- ✅ 水电开发页缩放跨过 `12` 级时,会自动补开一批动态图层;缩回去时再自动收口。(编排器层面处理)
|
||
- ✅ `2D` 存在"缩放越大显示越多"的行为。碰撞检测中密度门控逐级放开。
|
||
- ✅ `2D` 还存在 hover、批量 popup、密度控制等缩放阈值:
|
||
- hover 低于 ~zoom 4.5 不触发(`HOVER_POPUP_MAX_HEIGHT = 9_000_000`)
|
||
- 高缩放进入批量 popup 模式(`BATCH_POPUP_MODE_ZOOM = 14.9`)
|
||
- 点位随着缩放提升逐步放开密度限制(密度门控 + `DENSITY_ISOLATION_THRESHOLD`)
|
||
- ✅ **图标动态缩放**:`CallbackProperty` 实现 `billboard.scale`,公式 `clamp(0.7 + (zoom - 4.5) * 0.035, 0.4, 1.2)`(L1522)。
|
||
- ✅ **字体动态大小**:`CallbackProperty` 实现 `label.font`,钳位 `[10, 20]`(L1535)。
|
||
- ✅ **文字在图标上方**:`CallbackProperty` 实现 `label.pixelOffset`,负 Y 偏移(L1549)。
|
||
- ✅ **Cesium 中必须使用 `CallbackProperty` 实现动态缩放**:已使用 3 个 `CallbackProperty`(scale/font/offset),`isConstant=false` 每帧重算。
|
||
|
||
### 9.4 锚点碰撞与控量 ✅️
|
||
|
||
- ✅ `2D` 中锚点是否可见,不只受图层开关控制,还受以下门闩共同影响:
|
||
- 图例可见性 `_legendVisible`
|
||
- 区域裁切可见性 `_regionVisible`
|
||
- 密度阈值(碰撞循环中 inline 计算,逐级放开)
|
||
- 图标碰撞结果 `_iconCollisionVisible`
|
||
- 标签碰撞结果 `_labelCollisionVisible`
|
||
- ✅ 低缩放下,为避免堆叠,部分锚点或标签会被主动隐藏。(`refreshPointLabelVisibility` 碰撞检测,L2117-2455)
|
||
- ✅ 高缩放下,会逐步放开图标/标签限制,显示更多内容。(密度门控 + 碰撞容差随 zoom 调整)
|
||
- ✅ 因此 `3D` 不能简单把所有 entity 永久全开。所有 entity 初始 `_iconCollisionVisible = _labelCollisionVisible = true`,碰撞检测运行后动态调整。
|
||
|
||
### 9.5 Popup 与点击 ✅️
|
||
|
||
- ✅ hover popup 不是全时开启的,有缩放门槛。相机高度 > `HOVER_POPUP_MAX_HEIGHT` 时不触发 hover。
|
||
- ✅ 点击和 hover 的命中对象是图标本体,不是任意文字区域。`ScreenSpaceEventHandler` 基于 `scene.pick` 命中 entity。
|
||
- ✅ `ylfb` 与普通锚点的点击详情弹框走不同业务分支。`sttpMap === 'ylfb'` 打开 `ylfbModalVisible`,其他走 `modalVisible`(L366-375)。
|
||
|
||
### 9.6 基地与区域裁切 ✅️
|
||
|
||
- ✅ 基地切换不仅影响搜索候选,还会影响地图上的点位可见范围。`jdPanelControlShowAndHidden` 实现(L1684-1748)。
|
||
- ✅ 区域裁切会直接把区域外点位隐藏,不是只改底图遮罩。`filterPointsByRegion` 设置 `_regionVisible = false`(L1824-1848),遮罩多边形 + 裁剪双重处理。
|
||
|
||
### 9.7 筛选器特殊逻辑 ✅️
|
||
|
||
- ✅ 装机容量筛选本质是批量切 `eng_point` 图例状态,不是简单切图层。(store 层处理,Cesium 通过 `setLegendPointVisible` 响应)
|
||
- ✅ 鱼类分布模式会接管 `ylfb_point` 的数据、缓存、图例与显隐。(store 层处理)
|
||
- ✅ 时间筛选当前只重载指定时间相关图层,不是全量重载。(store 层处理)
|
||
|
||
### 9.8 数据进入 addInitDataLayer 前的预处理 ✅️
|
||
|
||
- ✅ 所有点位数据在进入 `addInitDataLayer` 前会经过 `normalizePointLayerItems()` 过滤:(store 层 `map.ts` 执行,Cesium 接收时已过滤)
|
||
- 没有 `iconCode` 且 `code !== 'colorLayer'` 的项会被抛弃
|
||
- `baseId == 'all'` 且 `anchoPointState` 结尾为 `_nbuilt` 的项会被抛弃
|
||
- ✅ `_id` 默认值生成规则:store 层生成 `${sttpMap || iconType || 'point'}_${stcd}`。
|
||
- ✅ **stcd+经纬度重复锚点处理**:Cesium entity ID 使用 `${layerKey}:${item._id}`,与 2D 对齐,同 stcd 不同 sttpMap 的点不会互相覆盖。
|
||
|
||
### 9.9 图标渐进加载机制
|
||
|
||
- ❌ 2D 中图标不是一次性全加载完。有 `loading → loaded → error` 三种状态跟踪。
|
||
- ❌ 只有 `loaded` 状态的图标才参与样式渲染,loader 失败的不渲染。
|
||
- ❌ 如果在图标加载过程中就触发了样式刷新,需要通过 `requestAnimationFrame` 回刷。
|
||
- ❌ 3D Cesium 中当前所有 entity 同步创建,billboard `image` URL 直接赋值,无渐进加载。Cesium 内部纹理加载无显式状态跟踪。
|
||
|
||
### 9.10 密度分档与近邻点元数据 ✅️
|
||
|
||
- ✅ 每个锚点的 `distance` 字段表示密度分档值(不是物理距离),值越大表示越稀疏。(已使用 `getEntityDensityValue` 从 `_rawData.distance` 读取,L2460)
|
||
- ✅ 不同 density 值对应不同的 `minZoom` 显示门槛。`getEntityDensityMinZoom` 映射 `nearby-point-rules.ts` 的 `densityDisplayRules`(L2491)。
|
||
- ✅ 全量数据加载后,store 会调用 `attachNearbyPointRuntimeMeta()` 给所有点打上 `_nearbyRule`、`_nearbyGroupId`、`_nearbyPriority` 等元数据。(store 层处理,Cesium 碰撞检测中读取)
|
||
- ✅ **孤立点例外规则**:如果一个点在当前视口内 ~56px 范围内没有同 layerKey 的其他可见点,它可以绕过密度门槛直接显示。`DENSITY_ISOLATION_THRESHOLD = 56` + `shouldBypassDensityGateForIsolatedEntity`(L2506-2556)。
|