专题页的迷雾按专题圈的区域收口

以前专题的中心/半径只用来定视图,迷雾图层一直是全局的;管理页那句
「迷雾由地图按视野自动呈现,不需要单独圈选」其实是把「没做」写成了
「不用做」。现在专题圈了区域时,迷雾只在那个圆内显示。

做法是给迷雾单独一个 pane(zIndex 250,底图 200 之上)再对该 pane 做
clip-path: circle()——不能直接裁 tilePane,底图也在里面,会把地图一起挖空。

两个坑:
- 圆心必须先 project() 到底图坐标系(与 fitCircle 一致),否则整体偏移;
- 裁剪圆的注册必须排在 applyFit() 之后:视图未定时 latLngToContainerPoint()
  会抛「Set map center and zoom first.」,把后续图层添加一起打断——实测
  表现是 pane 建好了、迷雾瓦片一张都不出来,而且不报错。

迷雾是累积快照、没有时间维度,所以只按区域收口,不按专题的时间范围收口。
守卫 TestTopicFogIsClippedToArea 钉住两端与注册顺序。
This commit is contained in:
tamakyi
2026-10-10 10:41:27 +08:00
parent cd69efe8f1
commit eb35abb7f2
7 changed files with 122 additions and 4 deletions
+30
View File
@@ -1078,5 +1078,35 @@ HTML,一行里必然带 `</script>`,一拒就把正常用法挡死了(我
一大片空白 —— `align-items: start` 只能消掉**卡内**的空白,消不掉并排本身的空。各占整行才对
(列表横铺、24 根柱也终于有宽度)。`align-items: start` 仍然保留:其它同行卡片也会体量不等。
## 四十五、专题的迷雾按区域收口(2026-10-10)
**现象**:用户建了专题问「迷雾好像无法根据选择显示范围?」。查下来是**实现缺口**,不是配置问题 ——
迷雾图层一直是全局的,专题的区域(中心+半径)只用来 `fitCircle` 定视图,跟迷雾完全无关。
管理页那句「区域内的世界迷雾由地图按视野自动呈现,**不需要单独圈选**」纯属**文档与实现不符**,
把「没做」写成了「不用做」。用户选的口径:**按专题区域收口**(不按时间收口)。
**实现**(`rond-map.js` + `topic.html`):`opts.fogArea = {lat, lon, radiusKm}` 由 `topic.html`
在 `.Topic.HasArea` 时下发;脚本给迷雾**单独建一个 pane** 再对该 pane 做 `clip-path: circle()`。
⚠️ 三个必踩的坑:
- **不能裁默认 `tilePane`** —— 底图瓦片也在那里面,裁下去地图跟着一起被挖空。所以
`map.createPane('rondFog')`(`zIndex=250`:底图 200 之上、覆盖物 400 之下,`pointerEvents='none'`),
迷雾 tileLayer 走 `pane: fogPane ? 'rondFog' : 'tilePane'`。
- **圆心必须 `project()` 到底图坐标系**(跟 `fitCircle` 一样),直接拿经纬度当容器坐标会整体偏出几百米。
半径用「同经度上偏移 radiusKm/111320 纬度」再量容器像素距离,随缩放自然变化。
- 🔴 **注册点必须排在 `applyFit()` 之后**。`latLngToContainerPoint()` 在视图未定时会抛
「Set map center and zoom first.」—— 实测放早了:pane 建好了、**迷雾瓦片一张都不出来**
(那行异常把后面所有图层添加一起打断,且不报错给用户,页面看着只是「迷雾没了」)。
正确写法:`applyFit(); if (applyFogClip) { map.on('move zoom viewreset resize', applyFogClip); applyFogClip(); }`
- 迷雾是**累积快照、没有时间维度** ⇒ 只按区域收口,不按专题的时间范围收口(管理页文案已写明)。
- 老浏览器不认 `clip-path` 只是「不裁剪」(退回全局迷雾),不会报错。
- 门禁 `TestTopicFogIsClippedToArea`:钉住两端 —— `topic.html` 得发 `fogArea:`、`rond-map.js` 得认
`opts.fogArea`/`createPane('rondFog')`/`clipPath`,且注册点下标 > `var applyFit = function` 的下标
(防的就是上面那个「放早了整片迷雾消失」)。
- 实测:临时专题 id=16(中心 24.698/108.075、半径 3km)→ `clip = circle(173px at 529px 260px)`,
反解半径正好 **3000 m**,`setZoom(9)` 后仍正确;`/map`、`/stats` 不受影响(它们没有 `fogArea`)。
- ⚠️ 用户自己的专题 `id=15`「2026年国庆」`radius_km=0` ⇒ 收口不生效,要在后台把中心与半径填上。