gis-view-webgl2 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/gis-view.css +1 -1
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.d.ts +250 -4
  4. package/dist/index.js +1 -1
  5. package/docs/AI/345/257/271/350/257/235/346/261/207/346/200/273.md +63 -11
  6. package/docs/GisView.md +6 -6
  7. package/docs/ai/06-/344/274/232/350/257/235/347/264/242/345/274/225/344/270/216/345/244/215/346/237/245/346/226/271/346/263/225.md +69 -11
  8. package/docs/demos/api-index.js +6 -2
  9. package/docs/demos/gis-view-demo/demo.css +56 -0
  10. package/docs/demos/gis-view-demo/panels/StylePanels.vue +22 -1
  11. package/docs/demos/gis-view-demo/panels/ViewPanels.vue +2 -1
  12. package/docs/demos/gis-view-demo/useGisViewDemo.js +168 -4
  13. package/docs/index.html +2 -2
  14. package/docs/internals/15-03-/351/200/220/350/275/256/350/256/260/345/275/225-/346/200/247/350/203/275/344/270/216/344/277/256/345/244/215-/344/270/213.md +72 -1
  15. package/docs/manual/03-/351/205/215/347/275/256/351/241/271.md +58 -4
  16. package/docs/manual/07-/346/214/207/351/222/210/344/270/216/350/246/201/347/264/240/347/274/226/350/276/221.md +1 -1
  17. package/docs/manual/08-/351/200/211/344/270/255/344/270/216/346/213/220/347/202/271.md +9 -4
  18. package/docs/manual/11-/346/240/267/345/274/217/344/270/216/350/247/204/345/210/231.md +2 -0
  19. package/docs/manual/13-/345/212/250/346/225/210/344/270/216/345/233/276/345/205/203.md +219 -1
  20. package/docs/manual/14-/350/247/206/345/233/276/344/270/216/347/255/233/351/200/211.md +3 -1
  21. package/docs/manual/15-/345/257/274/345/207/272/344/270/216/351/233/206/346/210/220.md +2 -2
  22. package/docs/manual/16-/345/256/236/344/276/213/346/226/271/346/263/225/346/200/273/350/241/250.md +2 -1
  23. package/docs/manual/17-/345/217/202/346/225/260/351/200/237/346/237/245.md +3 -1
  24. package/docs/manual/18-/351/200/220/346/226/271/346/263/225/347/244/272/344/276/213.md +8 -0
  25. package/docs/steps/selftest-demos.html +3 -3
  26. package/docs/steps/selftest-docs.html +4 -4
  27. package/docs/steps/selftest-features.html +736 -0
  28. package/docs/steps/selftest-perf.html +296 -25
  29. package/docs/steps/selftest-select.html +182 -1
  30. package/package.json +2 -2
@@ -1,6 +1,6 @@
1
1
  # AI 对话汇总
2
2
 
3
- > 一页读完 gis-view 的 AI 协作史:39 个会话、206 轮需求,按「关键决策 → 演进主线 → 精选问答」整理。
3
+ > 一页读完 gis-view 的 AI 协作史:39 个会话、211 轮需求,按「关键决策 → 演进主线 → 精选问答」整理。
4
4
  > 原先拆开的 01 ~ 05 已合并到这里;逐会话文件、历史增量索引与复查命令统一放在 [维护索引](ai/06-会话索引与复查方法.md)。
5
5
 
6
6
  这份汇总不是使用手册。组件行为以 [GisView 手册](GisView.md) 和 [数据格式](数据格式.md) 为准,实现细节与逐轮证据在 [GisView 实现原理](GisView实现原理.md) 的 `internals/15-*`、`16-*`。这里只回答三件事:当时为什么这么定、后来怎么演进、现在该从哪里继续查。
@@ -20,11 +20,11 @@
20
20
 
21
21
  | 项目 | 结论 |
22
22
  | --- | --- |
23
- | 对话范围 | 2026-09-15 ~ 2026-10-30,39 个会话、206 轮;10-14 之后主要为现有会话的增量轮次 |
24
- | 产品形态 | 一个无内置界面的 `createGisView(dom, options)` WebGL2 矢量视图,交互与视觉效果通过配置、事件和实例方法组合 |
23
+ | 对话范围 | 2026-09-15 ~ 2026-11-02,39 个会话、211 轮;10-14 之后主要为现有会话的增量轮次 |
24
+ | 产品形态 | 一个默认无控制面板的 `createGisView(dom, options)` WebGL2 矢量视图;鹰眼图、图例与背景编辑器按需开启,交互与视觉效果通过配置、事件和实例方法组合 |
25
25
  | 核心对象 | 节点、线路、通道(多回线 / 分组)、拐点、装饰、标签、覆盖层、鹰眼图、扩展图形 |
26
26
  | 技术路线 | WebGL2 批量渲染 + HTML / Canvas 覆盖层 + 网格索引 + 增量更新 + Worker 筛选与搜索 |
27
- | 当前公开面 | 281 个实例成员、105 个 options、273 个数据字段、44 个事件、17 个功能开关、16 个分组 |
27
+ | 当前公开面 | 283 个实例成员、107 个 options、275 个数据字段、44 个事件、17 个功能开关、16 个分组 |
28
28
  | 维护方式 | 文档双向对账、API 索引生成、14 个自测页与无头浏览器回归;每轮记录同步到本页与维护索引 |
29
29
 
30
30
  ## 关键技术决策
@@ -84,7 +84,59 @@
84
84
 
85
85
  先分清组件与宿主:本组件只负责接收已经整理好的点线数据,`initData` 只应在挂载时调用一次;若宿主定时重建数据,先查宿主路由、监听与 `gisTools.js` / `buildNewData`。SVG 被画成圆通常是宿主传入了错误的 `symbol` 或 `pointRules`,直流标记则要确认装饰类型与数据映射。历史排查见维护索引的 10-12 旁支记录。
86
86
 
87
- ## 当前轮次:fitSpacing.minDistance 精确落位与指定节点组间距(2026-10-30)
87
+ ## 当前轮次:toggleSelect 节点 / 线路 / 通道 / 分组核验与 visualMap 多目标门控(2026-11-02)
88
+
89
+ - **需求来源**:根目录 `修改.txt` —— ① 检查 `toggleSelect` 是否真的生效;② 续查对线路、通道和通道分组的取消是否生效;③ 反馈再次点击通道 / 线路 / 分组不会取消、只有节点能取消;④ 前一轮的 `visualMap` 交互没有效果、不会隐藏网架。
90
+ - **toggleSelect 根因与修复**:入口原先只看命中的那一条线路 `result.selected`。通道分组 / 整条通道只选中一部分,或点到组内、通道内的另一条回线时,这个值可能为 false,点击于是落到普通单选并重新选上,看起来只有节点能取消。现在 `engine.js` 抽出 `selectionScopeKeysOf()` 按 `channelSelectMode` 取得完整范围,`toggleSelect` 用范围 `anySelected` 判断,并以 `removeOnly` 整批取消;Ctrl / 多选仍保持原来的“整批取反 / 补缺”语义。独立线路、通道单条、完整分组、部分分组、完整通道、部分通道都有真实指针回归;`onClick` / `onSelectChange` 的动作名都是 `toggleSelect`。`selftest-select` 新增 6 条,107 → **113/0**。
91
+ - **toggleSelect 跨模式补充**:继续在真实 `?demo=full` 中复核发现默认 `channelSelectMode: 'line'` 下,先用 `selectFeatures` / 右键菜单完整选中一条通道或分组,再点回线只删除命中那一条,剩余成员仍在选中,视觉上仍像“通道 / 分组没有取消”。`engine.js` 新增 `selectionToggleScopeKeysOf()`:`line` 模式下若命中回线所属通道已完整选中,优先整条移除;否则若所属分组已完整选中,整组移除;部分选中仍按当前 `channelSelectMode` 摊开。真实指针复核:3 回线通道完整选中后点击其中一条,选中集由 3 条变为空。`selftest-select` 再增 2 条跨模式回归,113 → **115/0**;手册 03 / 08、`types.d.ts`、组件 README 同步。
92
+ - **GisEdit 配置链路复核与取消级联**:`D:\work\gis-view\src\components\GIS\GisEdit.vue` 实际配置为 `selectionKinds: ['point', 'lines']`、`channelSelectMode: 'channel'`。归一化后不含 `channel`,而 `toggleSelect` 取消分支仍检查了 `selectionKinds`,通道回线(分组回线也按 `channel` 归类)因此进不了取消路径;线路大多挂在通道下,用户看到的就是通道 / 线路 / 分组都不会取消。`engine.js` 移除该门控,保留开关、选中范围与双击判定;`selectionKinds` 继续只约束框选与 Ctrl / 多选。级联高亮改为在点击分流前判断这一下是否会取消:取消时直接清旧状态,避免同一击先发非空再发 `null`;接口 `deselect` / `selectFeatures` 的 remove / 清空经 `setSelection` 真正移除选中项时,也同步收掉级联并只补一条 `onCascadeHighlight(null)`。`selftest-select` 用真实 GisEdit 配置新增通道 / 分组回归,115 → **117/0**;`selftest-features` 新增 toggleSelect / deselect / remove 三条级联取消回归,839 → **842/0**。
93
+ - **visualMap 根因**:内部状态此前只保存单个 `target`,不写 `target` 时门控只落到 `heatmap.target` 的第一项 `point`;`new.json` 节点又没有 `max_loading_rate`,图例首项值域退化成空;Demo 构建通道时也没补这一列,`channel` 目标无值可判。三者叠加后,用户看到的图例既没有可用的值域,也不会隐藏线路 / 通道。
94
+ - **修复口径**:`visual-map.js` 内部快照与签名改带 `targets`,未显式写 `target` 时展示值域按 `point → line → channel` 选第一个真正有数值的目标,门控仍覆盖全部启用目标;`heatmap.js` 按目标组判断是否允许上色;`engine.js` 同时计算落选节点、独立线路与整条落选通道的成员回线,不再在第一个 `target` 处提前返回;`setVisualMapState()` 的影响面也按目标组判断。公开 API 不新增 `targets` 字段,计数保持 283 个实例成员 / 107 options / 275 数据字段。
95
+ - **Demo**:`buildNewData` 与 `buildSampleData` 的通道补成员最大 `max_loading_rate`;Demo 默认落选策略改为 `network`,面板提示明确不写 `target` 时三类一起门控。真实 `?demo=full` 复核:new.json 7368 节点 / 12811 线路 / 9230 通道,重新随机后图例自动切到 `point`(0.401 ~ 1.5),取消首段后可见节点 / 线路由 2123 / 4058 降到 0 / 0。
96
+ - **核心文件**:`src/gis-view/visual-map.js`、`heatmap.js`、`engine.js`、`create.js`、`types.d.ts`、`src/gis-view/README.md`;`docs/manual/03` / `07` / `08` / `11` / `13`、`docs/GisView.md`、Demo 组合式函数与样式面板、`selftest-features.html`、`selftest-select.html`、本页与维护索引。
97
+ - **验证**:`node --check src/gis-view/engine.js`、`npx tsc --noEmit`、API 索引、`npm run check:docs`、`npm run build`、`git diff --check` 通过;`selftest-select` **117/0**、`selftest-features` **842/0**、`selftest-actions` **96/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-perf` **197/0**。真实 `?demo=full` 用 3 回线通道和实际指针事件复核:完整通道选中后点击一条,选中集由 3 条变为空。性能页首次组合运行出现 192/5,失败项均为既有「线路标签候选复用」的排版时序,单独复跑全绿。
98
+
99
+ ## 上一轮次:再次选中取消、visualMap 落选门控与交互快路径(2026-11-01)
100
+
101
+ - **需求来源**:根目录 `修改.txt` 三条 —— ① 新增取消选中开关,默认关闭,单击、双击、Ctrl 先选中的路径都能再次操作取消;② 继续优化交互性能;③ `visualMap` 落选后应与热力图 / 网架联动,可选择消失对应网架或对应热力。按用户补充「不考虑分组详情」,本轮不扩展分组详情查询。
102
+ - **toggleSelect**:顶层 `options.toggleSelect` 缺省 `false`,由 `create.js` 透传引擎并支持 `updateOptions`。单击模式下第二次普通单击已选要素取反;`selectTrigger: 'dblClick'` 下由第二下取反、再次双击取消;Ctrl / ⌘ 先选中后再普通单击也取消。双击每轮只取反一次,不影响普通 `onClick` / `onDblClick` 的派发顺序;取反时 `onClick.action.type` 与 `onSelectChange.action.type` 都是 `toggleSelect`。
103
+ - **outOfRange**:`visualMap.outOfRange` 缺省 `'heatmap'`,只退出同一 `target` / `field` 的热力并恢复普通样式;`'network'` 额外隐藏落选节点、独立线路或整条通道成员,并从拾取与包围盒消失;`'none'` 不参与内置门控,只保留 `onChange`。`network` 的 `channel` 按声明收集全部成员回线,`line` 不误伤通道回线;数据、筛选、选中集与分组声明不变。图例状态、读数与 `onChange` 载荷都带 `outOfRange`。
104
+ - **交互性能**:引擎把筛选基线隐藏与 visualMap 视觉隐藏分成两套集合,解析时取并集;`network` 隐藏集合不变时 `setVisualMapState()` 返回 `hiddenChanged: false`,不重建场景。点 / 线热力样式缓存键分开,图例只影响节点时不再重算线路那一半;通道成员收集按通道声明一次完成。鹰眼图在 `network` 下同步隐藏,即使显式配置 `minimap.heatmap` 也不遮挡该语义。
105
+ - **Demo 与文档**:Demo 增加 `toggleSelect` 开关与落选值下拉;手册 03 / 08 / 13 / 14、`docs/GisView.md`、组件 README、API 索引同步。`selftest-select` 新增 5 条覆盖普通、双击、Ctrl、事件动作与关闭态;`selftest-features` 新增 8 条覆盖三种 `outOfRange`、节点 / 独立线路 / 通道、数据与筛选不变、隐藏集合快路径与鹰眼图同步。性能页的标签稳态用例改用 `progressiveInit: false` + `labelOptimize: true` 并显式等待 `isLayoutReady()`,避免锚点视图因发散渲染未完成而把第七轮首次真实排版误记成整屏重量。
106
+ - **核心文件**:`src/gis-view/engine.js`、`create.js`、`heatmap.js`、`visual-map.js`、`update-policy.js`、`types.d.ts`;`docs/manual/03` / `08` / `13` / `14`、`docs/GisView.md`、`src/gis-view/README.md`、Demo 组合式函数与面板、`selftest-select.html` / `selftest-features.html` / `selftest-perf.html`、本页、维护索引与 15.111。
107
+ - **验证**:`npx tsc --noEmit`、`npm run check:docs`、`npm run build`、`git diff --check` 通过;API 索引为 283 个实例成员(278 方法 + 5 属性)/ 107 options / 275 数据字段;串行自测 `selftest-select` **107/0**、`selftest-features` **836/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-perf` **197/0**。
108
+
109
+ ## 2026-11-01 更早轮次:热力密度几何隔离、线路热力连续与 visualMap 运行时门控(2026-11-01)
110
+
111
+ - **需求来源**:根目录 `修改.txt` 三条 —— ① 开启热力图后平移 / 缩放时仍有部分线路热力先消失再出现;② 开启热力图后背景也跟着异常放大缩小;③ `visualMap` 交互没有实际效果,应与 ECharts 一样影响热力表现。
112
+ - **背景缩放根因**:密度场虽然有自己的 `heatDensityBuffer`,绘制时却仍沿用背景图片的 `imageVao`;背景图片四边形一变,密度层就跟着缩放。现在新增独立 `heatDensityVao`,`drawImageQuad()` 可按层绑定几何,背景与密度场各用自己的 VAO,销毁时一并释放。
113
+ - **线路热力连续**:线路热力不再按 `interacting || cameraMoving` 在合并管线、细线快路径和两遍光晕之间切换。普通 / 自动浅底配置始终走 `drawHeatLineBatch()`;加法混合或驱动属性槽位不匹配时始终走两遍 `drawLineHeatGlow()`。自动画质降档也不再关闭线路热力;节点光晕仍可在交互期让路。
114
+ - **visualMap 实际门控**:`visual-map.js` 把当前分段 / 区间发成内部纯数据状态,`create.js` 在首帧及后续选择变化时交给引擎内部的 `setVisualMapState()`;`heatmap.js` 在选区外返回不参与热力。只门控与图例同 `target`、同 `field` 的要素,落选值回普通样式,不删除数据、不改筛选;分段空选择关闭对应热力,连续尺按闭区间判断。默认继承主图热力的鹰眼图也使用同一份状态,显式 `minimap.heatmap` 仍独立;没有新增公开实例成员 / options / 数据字段。
115
+ - **回归与文档**:`selftest-features` 增加分段勾选 / 取消、连续尺区间门控、密度权重、继承鹰眼图同选区与显式 `minimap.heatmap` 独立断言;`selftest-perf` 增加“图片背景不影响密度场几何”和逐条线路在运动 / 停稳帧的采样,两个用例都走真正的最终 PASS / FAIL。手册 03 / 11 / 13 / 14 / 15、`docs/GisView.md`、类型注释、组件 README 与 Demo 提示同步改成“内置门控 + onChange 额外联动”。
116
+ - **核心文件**:`src/gis-view/engine.js`、`heatmap.js`、`visual-map.js`、`create.js`、`types.d.ts`、`src/gis-view/README.md`;`docs/manual/03` / `11` / `13` / `15`、`docs/GisView.md`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`panels/StylePanels.vue`、`docs/steps/selftest-features.html` / `selftest-perf.html`、本页、维护索引与 15.110。
117
+ - **验证**:`node --check`、`npx tsc --noEmit`、`npm run check:docs`、`npm run build`、`git diff --check` 通过;串行自测 `selftest-features` **828/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-perf` **197/0**。性能页此前一次完整运行曾出现既有的“改一条可见标签之后的定向重排不读布局”读数断言失败(1313 次),最终复跑未再出现,与本轮热力改动无调用关系。
118
+
119
+ ## 2026-10-31 轮次:线路热力交互连续显示与 visualMap 自定义交互
120
+
121
+ - **需求来源**:根目录 `修改.txt` 三条 —— ① 开启热力图后平移 / 缩放时线路热力先消失再出现;② 继续优化热力图交互性能;③ 图例支持完全自定义与交互,参考 ECharts `visualMap`。
122
+ - **热力连续性**:`buildLineInstances()` 重铺线路实例时补 `heat: line.heat ?? 0`,修复相机移动后热力值归零;`LINE_VERTEX_SHADER` 改为把带符号的 `a_corner.y` 传到片元、再取 `abs(v_edge)`,修复插值后恒为 1 导致光晕衰减失效。交互 / 相机运动帧新增 `HEAT_LINE_FRAGMENT_SHADER` 与 `heatLineProgram`,一笔同时画本色核与光晕,预乘普通混合避免重叠线推白;停稳后的两遍仍按 `glow.blend`。
123
+ - **性能收口**:密度场四边形改用静态 `heatDensityBuffer`,交互 / 相机运动期跳过重烤、停稳补烤;节点光晕在交互期让路,线路热力经合并管线保持连续可见,减少圆面片和额外线绘制。
124
+ - **visualMap 交互**:`interactive` / `selectedMode` / `selected` / `range` / `calculable` 落地;分段支持点击与 Enter / Space 单选 / 多选,连续尺支持区间遮罩、双滑块、拖动单端 / 整体和方向键 / Shift / Alt / PageUp / PageDown / Home / End。`onChange` 一帧合并,载荷带 `source` / `reason` / `originalEvent` / `rangeRatios` 等;受控 `updateOptions({ visualMap })` 不回声。
125
+ - **完全自定义**:`render(context)` 可返回 DOM / DocumentFragment / HTML 字符串或直接写 `context.body`,上下文提供 `setSelection` / `setRange` / `clearSelection` / `emitChange`,可选择继续使用内置交互。`getVisualMap()` 同步返回交互状态、选择、区间与比例。
126
+ - **Demo 与文档**:热力面板增加图例交互 / 完全自定义开关和 `onChange` 读数;手册 03 / 11 / 13 / 15 / 16 / 17 / 18、`docs/GisView.md`、组件 README 与自测页同步。公开面保持 283 个实例成员(278 方法 + 5 属性)/ 106 options / 274 数据字段。
127
+ - **核心文件与验证**:核心为 `src/gis-view/shaders.js`、`engine.js`、`heatmap.js`、`visual-map.js`、`create.js`、`types.d.ts`、`gis-view.css`、Demo 与手册。`node --check`、`npx tsc --noEmit`、API 索引 / `npm run check:docs`、`npm run build`、`git diff --check` 通过;串行自测 `selftest-features` **823/0**、`selftest-perf` **195/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**。
128
+
129
+ ## 同日上一轮:visualMap 图例与图例专用快路径(2026-10-31)
130
+
131
+ - **需求来源**:根目录 `修改.txt` 两条 —— ① 参考 ECharts `visualMap`,增加类似图例,并结合 ruler 样式;② 继续优化组件性能。
132
+ - **图例能力**:新增 `visualMap` option 与 `src/gis-view/visual-map.js`。`ruler` / `continuous` 画连续渐变尺与刻度,`piecewise` 画分段色块;支持 ECharts 风格 `pieces`(`gte` / `gt` / `lte` / `lt` / `min` / `max`)、显式 `domain` / `min` / `max`、`colors` / `stops` / `opacity`、标题与单位、格式化、方向 / 定位 / 尺寸、外部容器与自定义样式。不写字段 / 值域 / 色带时继承 `heatmap`;没有热力图也能按 `field` 独立扫值域。
133
+ - **边界与接入**:不配 / `null` / `enabled: false` 时不挂载节点;`getVisualMapElement()` 给根节点,`getVisualMap()` 给类型、目标、字段、值域、颜色、刻度 / 分段读数。默认 `pointer-events: none`,交互式区间图例由使用方在这层 DOM 上扩展。
134
+ - **性能快路径**:图例与画布共用 `createHeatmapRamp()` 的色带插值;更新走 rAF 合帧与渲染签名缓存,同一签名零 DOM 写入。数据变化只记脏并在下一帧按需重扫,图例侧自动值域在本次配置生命周期内复用自身解析缓存;显式 `domain`、以及两端都写死的 `min` / `max` 都跳过扫描。`updateOptions({ visualMap })` 绕过引擎场景、鹰眼图与标签层重排,连续滑块只保留每帧一次重画。
135
+ - **Demo 与文档**:热力图面板增加「显示图例」与「连续尺 / 分段」控件,默认跟随当前热力图。手册 03 / 11 / 13 / 15 / 16 / 17 / 18、组件 README、文档中心与四个自测页同步;实例成员 281 → **283**(方法 276 → **278**,属性仍 5),options 105 → **106**,数据字段 273 → **274**,分组仍 16。
136
+ - **核心文件**:`src/gis-view/visual-map.js`、`heatmap.js`、`create.js`、`gis-view.css`、`types.d.ts`、`src/gis-view/README.md`;手册 03 / 11 / 13 / 15 / 16 / 17 / 18、`docs/index.html`、Demo 样式面板与组合式函数、`docs/steps/selftest-features.html` / `selftest-perf.html` / `selftest-demos.html` / `selftest-docs.html`、API 索引、本页、维护索引与 15.108。
137
+ - **验证**:`npx tsc --noEmit`、`node --check`(图例 / 热力图 / 组件入口 / Demo)、`node docs/steps/gen-api-index.mjs`、`gen-api-index.mjs --check`、`npm run check:docs`(283 个实例成员 / 278 个方法 / 5 个属性 / 106 个 options / 274 个数据字段)、`npm run build`、`git diff --check` 通过;浏览器自测 `selftest-features` **808/0**、`selftest-perf` **190/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-demo` **133/0**。
138
+
139
+ ## 上两轮:fitSpacing.minDistance 精确落位与指定节点组间距(2026-10-30)
88
140
 
89
141
  - **需求来源**:根目录 `修改.txt` 三条 —— ① `minDistance` 一旦设置就必须按该屏幕距离显示,不能因为初始值或“贴边”限制只能变大;② 新增方法,传一组节点返回整组的 `minDistance` / `maxDistance`;③ 文档说明两者如何按坐标与放大比例计算。
90
142
  - **精确屏距根因**:`fitSpacingAdjustment()` 原来用 `Math.max(普通适应比例, minDistance / 最近世界距离)`,并再用 `maxZoom` 截断;因此目标比例比当前小时完全不生效。现在 `minDistance` 分支直接令 `target = minDistance / nearestWorldDistance`,放大 / 缩小都覆盖普通适应,`maxZoom` 仅兼容保留,最终只受 `minScale` / `maxScale` 夹取;相机中心仍沿用普通包围盒中心。
@@ -94,7 +146,7 @@
94
146
  - **核心文件**:`src/gis-view/engine.js`、`create.js`、`types.d.ts`、`src/gis-view/README.md`;`docs/manual/03` / `14` / `16` / `17` / `18`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`panels/StylePanels.vue`、`docs/steps/selftest-scale.html`、`selftest-docs.html`、`selftest-demos.html`、`docs/demos/api-index.js`、本页、维护索引与 15.107。
95
147
  - **验证**:`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs`、`npm run check:docs`(281 个实例成员 / 276 个方法 / 105 个 options / 273 个数据字段)、`npm run build`(仅既有大 chunk 提示)、`git diff --check` 通过;浏览器串行自测 `selftest-features` **794/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-demo` **133/0**;`selftest-scale` **126 通过 / 2 失败**,5 条新增断言全过,2 条仍是既有筛选回调时序(`onFilter 0 条`)。
96
148
 
97
- ## 上一轮:背景文字同帧刷新与 fitSpacing.minDistance 上限修复(2026-10-30)
149
+ ## 上三轮:背景文字同帧刷新与 fitSpacing.minDistance 上限修复(2026-10-30)
98
150
 
99
151
  - **需求来源**:根目录 `问题.txt` 两条 —— ① 拖动 GeoJSON 背景时仍有晃动,文字尤其明显;② `fitSpacing.minDistance` 有时怎么调都不生效,而 `maxDistance` 正常,怀疑内部还有强制限制。
100
152
  - **背景文字根因**:内置背景编辑器每帧先更新 WebGL 背景与编辑框,但区域文字由 `setBackgroundLabels()` 排进下一帧 rAF;底图已经移动、文字还停在上一位置,合成后就是拖影 / 晃动。
@@ -105,7 +157,7 @@
105
157
  - **核心文件**:`src/gis-view/engine.js`、`overlay.js`、`create.js`、`types.d.ts`、`README.md`;`docs/manual/03` / `14`、`docs/from0/15`、`docs/demos/api-index.js`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`docs/steps/selftest-features.html`、`selftest-scale.html`、`selftest-demo.html`、本页、维护索引与 15.106。
106
158
  - **验证**:`npx tsc --noEmit` 0 错;`node docs/steps/gen-api-index.mjs` 更新 280 个实例成员的索引;`npm run check:docs` 全绿(280 个实例成员 / 105 个 options / 273 个数据字段);`npm run build` 通过;`git diff --check` 通过。浏览器串行自测:`selftest-features` **794/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-demo` **133/0**;`selftest-scale` **121 通过 / 2 失败**,新增的小量纲断言通过,两条失败仍是既有筛选回调时序(`onFilter 0 条`)。
107
159
 
108
- ## 上两轮:内置背景编辑器与旋转按钮命中修复(2026-10-30)
160
+ ## 上四轮:内置背景编辑器与旋转按钮命中修复(2026-10-30)
109
161
 
110
162
  - **需求来源**:根目录 `修改.txt` 两条 —— ① 旋转按钮始终不旋转;② 把整块背景编辑模式做成内置模块,通过方法开启和配置,不再由 Demo 纯手写。
111
163
  - **旋转按钮修复**:旧 Demo 的 `.bg-edit-layer` 整体是 `pointer-events: none`,缩放手柄与轮廓单独恢复 `auto`,但旋转按钮漏了同一个设置,因此按钮可见却收不到指针。内置编辑器为旋转按钮显式恢复 `pointer-events: auto`;`selftest-demos` 改用 `document.elementFromPoint()` 验证按钮真实可命中,再拖动旋转,避免只对按钮直接派发合成事件而漏掉命中问题。
@@ -116,7 +168,7 @@
116
168
  - **核心文件**:`src/gis-view/background-editor.js`(新增)、`gis-view.css`、`create.js`、`types.d.ts`;`docs/demos/BackgroundDemo.vue`、`demos.js`、`docs/manual/03` / `14` / `16` / `17` / `18` / `21`、`docs/internals/14`、`docs/steps/selftest-demos.html`、`selftest-features.html`、`selftest-docs.html`、本页、维护索引与 15.105。
117
169
  - **验证**:`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs`、`npm run check:docs`(280 个实例成员 / 105 个 options / 273 个数据字段)、`npm run build`、`git diff --check` 通过;浏览器串行自测 `selftest-features` **793/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**。
118
170
 
119
- ## 上三轮:背景编辑 4 / 8 / 9 点、旋转开关与可定制编辑框(2026-10-30)
171
+ ## 上五轮:背景编辑 4 / 8 / 9 点、旋转开关与可定制编辑框(2026-10-30)
120
172
 
121
173
  - **需求来源**:根目录 `修改.txt` 五条 —— ① 只有开启旋转时才显示旋转按钮;② 取消宽高锁定后从四角改为常见八点,开启旋转后变成九点,并考虑背景角度;③ 背景编辑框样式支持自定义;④ 修复移动背景图的轻微晃动;⑤ 全部在 demo 中体现。
122
174
  - **编辑点与旋转**:`BackgroundDemo.vue` 锁定比例时仍显示四角等比缩放;解锁后增加上下左右四个边中点,共八个缩放手柄;旋转开关独立于宽高锁定,只有勾选“允许旋转”才生成顶部旋转点和旋转连线,因此解锁并开启旋转时共九个编辑点。关闭旋转只收起旋转点,保留当前角度与八个缩放手柄。
@@ -128,7 +180,7 @@
128
180
  - **核心文件**:`docs/demos/BackgroundDemo.vue`、`docs/demos/demos.js`、`docs/manual/03-配置项.md`、`docs/manual/14-视图与筛选.md`、`docs/manual/21-说明与常见问题.md`、`docs/steps/selftest-demos.html`、本页、维护索引、15.104。
129
181
  - **验证**:`npx tsc --noEmit`、`npm run check:docs`(276 个实例成员 / 105 个 options / 273 个数据字段)、`npm run build`、`git diff --check` 通过;浏览器串行自测 `selftest-features` **786/0**、`selftest-demos` **440/0**、`selftest-docs` **139/0**。
130
182
 
131
- ## 上四轮:背景移动 / 旋转、背景编辑模式与网架整体显隐(2026-10-30)
183
+ ## 上六轮:背景移动 / 旋转、背景编辑模式与网架整体显隐(2026-10-30)
132
184
 
133
185
  - **需求来源**:根目录 `修改.txt` 两条 —— ① 背景可以调整位置并旋转;调整背景时网架不能拖拽、点击或以其他方式操作,但能和背景一起整体放大缩小,相当于只编辑背景或进入背景编辑模式;② Demo 明显有问题。此前同日一轮已补背景添加、四角调整与网架整体显隐 / 透明度,本轮在其上完成移动、旋转与编辑模式,并修好 Demo 的旧文案、旧状态和交互缺口。
134
186
  - **背景移动与旋转**:`background.geoJsonStyle.bounds` 把整份解析后的 GeoJSON 独立缩放 / 平移到目标世界矩形,`geoJsonStyle.rotation` 再绕目标矩形中心顺时针旋转;填充、描边、点、逐区域范围、重心与区域文字一起变换,`rawBounds` 保持原始坐标,解析后的 `bounds` 是旋转后的轴对齐外框。图片用旋转后的 `image.corners` 表达同一位置 / 角度,不改原始数据。
@@ -138,7 +190,7 @@
138
190
  - **核心文件**:`src/gis-view/engine.js`、`background.js`、`create.js`、`overlay.js`、`update-policy.js`、`types.d.ts`;`docs/demos/BackgroundDemo.vue`、`demos.js`、`docs/demos/api-index.js`、`docs/manual/03` / `14` / `16` / `18` / `21`、`docs/steps/selftest-features.html`、`selftest-demos.html`、`selftest-docs.html`、本页与维护索引、15.102 / 15.103。
139
191
  - **验证**:`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs`、`npm run check:docs`(276 个实例成员 / 105 个 options / 273 个数据字段)、`npm run build`、`git diff --check` 通过;浏览器串行自测 `selftest-features` **786/0**、`selftest-demos` **433/0**、`selftest-docs` **139/0**。
140
192
 
141
- ## 上五轮:交互样式优先级回归、单 / 多要素样式 Demo 与详情查询(2026-10-30)
193
+ ## 上七轮:交互样式优先级回归、单 / 多要素样式 Demo 与详情查询(2026-10-30)
142
194
 
143
195
  - **需求来源**:根目录 `修改.txt` 三条 —— ① 选中 / 框选 / 多选 / 级联等交互颜色始终最高,不受规则束缚;② 增加修改单个或多个节点 / 线路样式的 demo;③ 说明如何查询单个或多个节点、线路、通道的详情。按本轮补充要求,分组详情不纳入改动。
144
196
  - **交互样式优先级**:现有解析链保持「状态样式 / 热力图 > override 规则 > 要素自身 > 普通规则 > 全局样式 > 默认值」不变;核对窄样式快路径只在无规则、无热力图时启用,不会绕过状态层。新增浏览器回归覆盖单选、动态切换 override 规则、多选节点 / 线路、框选节点 / 线路与级联,证明颜色不会被强制规则改回业务色;线路框选沿用 `lineSelectStyle`。
@@ -147,7 +199,7 @@
147
199
  - **核心文件**:`docs/demos/StyleDemo.vue`、`docs/demos/demos.js`、`docs/manual/11-样式与规则.md`、`docs/manual/18-逐方法示例.md`、`docs/steps/selftest-features.html`、`docs/steps/selftest-demos.html`、本页、维护索引与 15.101。
148
200
  - **验证**:`npx tsc --noEmit`、`npm run check:docs`(276 个实例成员 / 102 个 options / 270 个数据字段)、`npm run build`、`git diff --check` 通过;`selftest-features` 778/0、`selftest-demos` 415/0、`selftest-docs` 138/0。未改公开 API,API 计数不变。
149
201
 
150
- ## 更早一轮:规则优先级分层、单要素样式说明与解析性能(2026-10-30)
202
+ ## 上八轮:规则优先级分层、单要素样式说明与解析性能(2026-10-30)
151
203
 
152
204
  - **需求来源**:根目录 `修改.txt` 四条 —— ① 规则样式始终高于外层 `pointStyle` / `lineStyle`,但默认低于要素自身样式;② 单条规则可用 `override: true` 压过要素自身样式;③ 补充单个节点 / 单条线路改颜色、尺寸、图标等样式的方法;④ 继续优化组件性能。
153
205
  - **规则优先级**:统一为「状态样式 / 热力图 > override 规则 > 要素自身样式 > 普通规则 > 外层 `pointStyle` / `lineStyle` > 默认值」。普通规则不再被外层样式遮住,但也不会抢要素自己写的字段;所有层都按字段生效,未写字段继续向下回落,状态样式与热力图始终最高。同一层多条规则仍按声明顺序后命中覆盖先命中。
package/docs/GisView.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # GisView
2
2
 
3
- `GisView` 是一套不依赖任何第三方图形库的 WebGL2 矢量视图:渲染层是原生 WebGL2(GLSL ES 3.00 + 实例化绘制),交互层只有指针与滚轮,界面只内置可选的小地图与背景编辑器(分别配 `minimap` / 调 `beginBackgroundEdit()` 才有,见「鹰眼图」「背景层」),其余全靠使用方。它没有 Vue 组件形态,用 `createGisView(dom, options)` 把画布直接挂到传入的 DOM 上,宽高默认跟随容器。
4
-
5
- 控制面板、读数面板、图例这类视图工具都不内置:组件只提供画布与实例方法,样式和布局完全由使用方决定,后续改样式不需要等待组件升级。数据侧该有的都给了:按属性筛选(默认只隐藏,也可显式从数据删除;点被过滤时绑定线路与通道一起消失,大数据量走 Web Worker)、按属性批量配色换符号、节点标签与点 / 线 / 通道的悬浮提示,都可以通过 options 或实例方法配置。
3
+ `GisView` 是一套不依赖任何第三方图形库的 WebGL2 矢量视图:渲染层是原生 WebGL2(GLSL ES 3.00 + 实例化绘制),交互层只有指针与滚轮,界面只内置可选的小地图、热力图图例与背景编辑器(分别配 `minimap` / `visualMap` / 调 `beginBackgroundEdit()` 才有,见「鹰眼图」「图例(visualMap)」「背景层」),其余全靠使用方。它没有 Vue 组件形态,用 `createGisView(dom, options)` 把画布直接挂到传入的 DOM 上,宽高默认跟随容器。
4
+
5
+ 控制面板与读数面板不内置;需要热力图图例时也不必自建:`options.visualMap` 会画一条带刻度的连续色带(`ruler` / `continuous`)或一组分段色块(`piecewise`),默认跟随 `heatmap` 的字段、值域与颜色。显式写 `target` 时选区只门控这一类;不写时展示值域取第一类有数值的启用目标,选区却覆盖全部启用目标上同 `field` 的热力上色、光晕与密度。图例本身就能点选分段、拖动筛选区间;默认继承主图热力的鹰眼图同步门控,显式 `minimap.heatmap` 仍独立。落选值由 `outOfRange` 选择只回普通样式(`'heatmap'`,缺省)、把对应节点 / 独立线路 / 通道一起隐藏(`'network'`),或完全不做内置门控而只发 `onChange`(`'none'`);三种方式都不删除数据、不改筛选。额外业务联动仍可听 `onChange`。需要「再次点击已选中要素即取消」时打开 `toggleSelect`(缺省关),普通单击、双击与 Ctrl 选中后的普通单击都适用。需要完全换一套外观时用 `render(context)` 接管内容,不必再写插件。其余样式和布局由使用方决定,后续改样式不需要等待组件升级。数据侧该有的都给了:按属性筛选(默认只隐藏,也可显式从数据删除;点被过滤时绑定线路与通道一起消失,大数据量走 Web Worker)、按属性批量配色换符号、节点标签与点 / 线 / 通道的悬浮提示,都可以通过 options 或实例方法配置。
6
6
 
7
7
  **这份手册按主题拆成了 21 章,正文在 [`docs/manual/`](manual/) 下**:找方法先看 [16 实例方法总表](manual/16-实例方法总表.md),查参数跳 [17 参数速查](manual/17-参数速查.md),要能直接复制的调用看 [18 逐方法示例](manual/18-逐方法示例.md);只想先跑起来看 [01 快速开始](manual/01-快速开始.md)。
8
8
 
@@ -28,11 +28,11 @@
28
28
  | [10 通道编辑与新增](manual/10-通道编辑与新增.md) | 分组拐点的增删、右键交互框、新增通道的草稿流程、改名与增删回线 |
29
29
  | [11 样式与规则](manual/11-样式与规则.md) | 点配置、线配置、条件语言(筛选 / 规则 / 标签共用)与批量样式规则 |
30
30
  | [12 标签与装饰](manual/12-标签与装饰.md) | 节点 / 线路标签、标签拖动与编辑、节点与线路装饰、动态装饰器草稿、悬浮提示 |
31
- | [13 动效与图元](manual/13-动效与图元.md) | 热力图、动画效果、线路方向箭头、贴图预热与自定义图元 |
31
+ | [13 动效与图元](manual/13-动效与图元.md) | 热力图、图例(visualMap)、动画效果、线路方向箭头、贴图预热与自定义图元 |
32
32
  | [14 视图与筛选](manual/14-视图与筛选.md) | 筛选、搜索定位、初始视图与缩放范围、背景层、鹰眼图、近义入口 |
33
33
  | [15 导出与集成](manual/15-导出与集成.md) | 导出图片 / 选中节点 / 数据、自定义导出格式,插件、自建界面与键盘交互 |
34
34
  | [16 实例方法总表](manual/16-实例方法总表.md) | 按功能分组的实例方法主表(找方法从这一章开始) |
35
- | [17 参数速查(逐个方法)](manual/17-参数速查.md) | 281 个成员逐个列全:参数、默认值与返回 |
35
+ | [17 参数速查(逐个方法)](manual/17-参数速查.md) | 283 个成员逐个列全:参数、默认值与返回 |
36
36
  | [18 逐方法示例(复制就能跑)](manual/18-逐方法示例.md) | 每个成员一段可复制的调用示例(API 速查页读的就是这一章) |
37
37
  | [19 读数与拖拽预览](manual/19-读数与拖拽预览.md) | 自建界面常用的读数 / 定位方法;拖拽落点预览 |
38
38
  | [20 性能与大数据](manual/20-性能与大数据.md) | 十万级数据的开关与实测、WebGPU 取舍、渲染后端开关 |
@@ -44,7 +44,7 @@
44
44
  - **配置与回调**:[options 总表](manual/03-配置项.md#options) · [回调](manual/04-事件与回调.md#回调) · [功能开关](manual/04-事件与回调.md#功能开关)
45
45
  - **通道**:[通道与多回线](manual/09-通道与多回线.md) · [通道编辑与新增](manual/10-通道编辑与新增.md) · [分组拐点](manual/10-通道编辑与新增.md#分组拐点把某一组拉走)
46
46
  - **样式**:[点配置](manual/11-样式与规则.md#点配置) · [线配置](manual/11-样式与规则.md#线配置) · [条件语言](manual/11-样式与规则.md#条件语言) · [批量样式规则](manual/11-样式与规则.md#批量样式规则)
47
- - **标签与动效**:[节点标签](manual/12-标签与装饰.md#节点标签) · [线路标签](manual/12-标签与装饰.md#线路标签) · [标签优化](manual/12-标签与装饰.md#标签显示优化开关labeloptimize) · [扩展图形](manual/12-标签与装饰.md#扩展图形graphic) · [节点装饰](manual/12-标签与装饰.md#节点上的装饰图片--svg) · [线路装饰](manual/12-标签与装饰.md#线路上的装饰图片--svg) · [手动删除装饰](manual/12-标签与装饰.md#手动删除装饰) · [动态装饰器](manual/12-标签与装饰.md#动态装饰器草稿) · [动画效果](manual/13-动效与图元.md#动画效果effects) · [自定义图元](manual/13-动效与图元.md#自定义图元)
47
+ - **标签与动效**:[节点标签](manual/12-标签与装饰.md#节点标签) · [线路标签](manual/12-标签与装饰.md#线路标签) · [标签优化](manual/12-标签与装饰.md#标签显示优化开关labeloptimize) · [扩展图形](manual/12-标签与装饰.md#扩展图形graphic) · [节点装饰](manual/12-标签与装饰.md#节点上的装饰图片--svg) · [线路装饰](manual/12-标签与装饰.md#线路上的装饰图片--svg) · [手动删除装饰](manual/12-标签与装饰.md#手动删除装饰) · [动态装饰器](manual/12-标签与装饰.md#动态装饰器草稿) · [图例(visualMap)](manual/13-动效与图元.md#图例visualmap) · [动画效果](manual/13-动效与图元.md#动画效果effects) · [自定义图元](manual/13-动效与图元.md#自定义图元)
48
48
  - **视图**:[筛选](manual/14-视图与筛选.md#筛选) · [搜索与定位](manual/14-视图与筛选.md#搜索与定位) · [适应视图的节点间距](manual/14-视图与筛选.md#适应视图的节点间距fitspacing) · [背景层](manual/14-视图与筛选.md#背景层) · [鹰眼图](manual/14-视图与筛选.md#鹰眼图)
49
49
  - **导出与集成**:[导出数据](manual/15-导出与集成.md#导出数据) · [自定义导出格式](manual/15-导出与集成.md#自定义导出格式后端-dto) · [插件](manual/15-导出与集成.md#插件) · [实例命令](manual/15-导出与集成.md#实例命令) · [六类扩展点怎么选](manual/15-导出与集成.md#六类扩展点怎么选) · [自建界面](manual/15-导出与集成.md#自建界面)
50
50
  - **查方法**:[实例方法总表](manual/16-实例方法总表.md) · [参数速查](manual/17-参数速查.md) · [逐方法示例](manual/18-逐方法示例.md) · [读数与拖拽预览](manual/19-读数与拖拽预览.md)
@@ -55,6 +55,11 @@
55
55
 
56
56
  | 日期 | 这一轮 |
57
57
  | --- | --- |
58
+ | 2026-11-02 | 增量:(「修改.txt」两条:GisEdit toggleSelect 被 selectionKinds 拦截 / 取消选中同步收掉级联) |
59
+ | 2026-11-01 | 增量:(「修改.txt」三条:toggleSelect 再次选中取消 / visualMap outOfRange 落选门控 / 交互性能) |
60
+ | 2026-11-01 | 增量:(「修改.txt」三条:热力密度几何隔离 / 线路热力连续 / visualMap 运行时门控) |
61
+ | 2026-10-31 | 增量:(「修改.txt」三条:线路热力交互连续显示 / 热力性能 / visualMap 自定义交互) |
62
+ | 2026-10-31 | 增量:(「修改.txt」两条:visualMap 连续尺 / 分段图例 / 图例专用快路径 / 继续优化性能) |
58
63
  | 2026-10-30 | 增量:(「修改.txt」三条:minDistance 精确落位 / 指定节点组间距 / 距离公式文档) |
59
64
  | 2026-10-30 | 增量:(「问题.txt」两条:GeoJSON 背景拖动文字晃动 / `fitSpacing.minDistance` 被缺省 `maxScale` 截断) |
60
65
  | 2026-10-30 | 增量:(「修改.txt」两条:旋转按钮失效修复 / 背景编辑器内置为方法模块) |
@@ -129,7 +134,60 @@
129
134
  | 2026-10-19 | 增量:(「修改.txt」继续优化与排查) |
130
135
  | 2026-10-19 | 增量:(「修改.txt」五条) |
131
136
 
132
- ## 三、当前增量:fitSpacing.minDistance 精确落位与指定节点组间距(2026-10-30)
137
+ ## 三、当前增量:toggleSelect 节点 / 线路 / 通道 / 分组核验与 visualMap 多目标门控(2026-11-02)
138
+
139
+ - **需求来源**:根目录 `修改.txt`:① 检查 `toggleSelect` 是否真的生效;② 续查对线路、通道和通道分组的取消是否生效;③ 反馈再次点击通道 / 线路 / 分组不会取消、只有节点能取消;④ 前一轮的 `visualMap` 交互没有效果、不会隐藏。
140
+ - **toggleSelect 根因与修复**:入口原先只判断命中的那一条线路 `result.selected`。通道分组 / 整条通道只选中一部分,或点到组内、通道内的另一条回线时,这个值可能为 false,点击会落到普通单选并重新选上,表现得像只有节点能取消。现在 `engine.js` 的 `selectionScopeKeysOf()` 统一按 `channelSelectMode` 求展开范围;`toggleSelect` 用范围 `anySelected` 判断,并以 `removeOnly` 整批取消,不再要求命中的恰好是那条已选回线;Ctrl / 多选路径仍保持原来的整批取反 / 补缺语义。新增独立线路、通道单条、完整 / 部分分组、完整 / 部分通道 6 条指针回归,两条选中回调都报 `toggleSelect`;`selftest-select` 107 → **113/0**。
141
+ - **toggleSelect 跨模式补充**:真实 `?demo=full` 再复核发现,默认 `channelSelectMode: 'line'` 时,用 `selectFeatures` / 右键菜单先完整选中整条通道或分组,再点回线只会移除命中那一条,剩余成员仍选中,视觉上仍像通道 / 分组没有取消。`engine.js` 新增 `selectionToggleScopeKeysOf()`:`line` 模式下,命中回线所属通道完整选中时优先整条取消,否则分组完整选中时整组取消;部分选中仍按当前模式摊开,Ctrl / 多选不变。`?demo=full` 用 3 回线通道和真实 `pointerdown` / `pointerup` 验证:完整通道选中后点击一条,选中集由 3 条变为空。`selftest-select` 再增 2 条,113 → **115/0**;手册 03 / 08、`types.d.ts`、组件 README 同步。
142
+ - **GisEdit 配置链路复核与取消级联**:`D:\work\gis-view\src\components\GIS\GisEdit.vue` 实际是 `selectionKinds: ['point', 'lines']`、`channelSelectMode: 'channel'`。`selection.js` 把 `'lines'` 归一成 `'line'`,所以 `channel` 不在允许集合里;但 `engine.js` 的 `toggleSelect` 取消分支仍检查 `selectionKinds`,通道回线(分组回线也归为 `channel`)根本没进入取消路径,普通点击又把它重新选上。线路大多属于通道,因此 GisEdit 里看到的是通道 / 线路 / 分组都不会取消。现在移除该门控,`selectionKinds` 继续只约束框选与 Ctrl / 多选,与 `types.d.ts`、手册 03 / 08 的既有口径一致;`selftest-select` 直接用 `['point', 'lines'] + channelSelectMode: 'channel'` 复现 GisEdit 配置,覆盖整条通道与完整分组取消,115 → **117/0**。
143
+ - **取消选中时级联收尾**:此前级联高亮在点击分流之前无条件提交,toggleSelect / Ctrl 取反等真正取消选中时可能先发一次非空再发 `null`,接口取消则完全不会收。`engine.js` 抽出 `updateCascadeForClick()`:会取消的点击只清旧级联;普通选择与新增选择仍按 `triggerOnClick` / `triggerOnMultiSelect` 更新。`setSelection` 发现本次移除了选中键时也调用 `clearCascadeHighlightState()`,因此 `deselect`、`selectFeatures(..., { mode: 'remove' })`、`selectFeatures(null)` 都会同步收掉级联并只发一条 `onCascadeHighlight(null)`。`selftest-features` 新增 toggleSelect、deselect、selectFeatures remove 三条回归,839 → **842/0**。
144
+ - **visualMap 根因**:内部状态此前只有单个 `target`,不写 `target` 时门控只取 `heatmap.target` 第一项 `point`;`new.json` 节点没有 `max_loading_rate`,图例展示值域退化为空;Demo 构建通道时也没写这一列,`channel` 分支没有可判定的值。因此图例看起来既不显示有效值域,也不会隐藏线路 / 通道。
145
+ - **多目标门控**:`visual-map.js` 内部快照 / 签名加入 `targets`,未显式写 `target` 时展示值域按 `point → line → channel` 选第一个真正有数值的目标,门控覆盖全部启用目标;`heatmap.js` 的 `visualStateAllows()` 按 `targets` 匹配;`engine.js` 的 `computeVisualHiddenIndexes()` 同时处理落选节点、独立线路与整条落选通道,`setVisualMapState()` 的 `affectsPoint` / `affectsLine` 也按目标组判断。公开面不增加 `targets` 字段,仍为 283 个实例成员(278 方法 + 5 属性)/ 107 options / 275 数据字段。
146
+ - **Demo 与回归**:`buildNewData` / `buildSampleData` 给通道补成员最大 `max_loading_rate`,Demo 默认 `visualMapOutOfRange` 改为 `network`,面板提示说明不写 `target` 时三类一起门控。`selftest-features` 新增 3 条:节点缺字段时图例展示值域切到 `line`、多目标 `network` 同时隐藏三类、恢复全选后全部回画布。真实 `?demo=full` 复核:7368 节点 / 12811 线路 / 9230 通道;重新随机后图例自动切到 `point`(0.401 ~ 1.5),取消首段后可见节点 / 线路由 2123 / 4058 降到 0 / 0。
147
+ - **核心文件**:`src/gis-view/visual-map.js`、`heatmap.js`、`engine.js`、`create.js`、`types.d.ts`、`src/gis-view/README.md`;`docs/manual/03` / `07` / `08` / `11` / `13`、`docs/GisView.md`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`panels/StylePanels.vue`、`docs/steps/selftest-features.html`、`selftest-select.html`、本页与 `docs/AI对话汇总.md`。
148
+ - **验证**:`node --check src/gis-view/engine.js`、`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs`、`npm run check:docs`、`npm run build`、`git diff --check` 通过;串行自测 `selftest-select` **117/0**、`selftest-features` **842/0**、`selftest-actions` **96/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-perf` **197/0**。真实 `?demo=full` 以实际指针事件复核完整通道取消,选中集由 3 条变为空。性能页首次组合运行出现 **192/5**,5 条均为既有「线路标签候选复用」的标签排版时序,单独复跑全绿,与本轮改动没有调用关系。
149
+
150
+ ## 四、上一增量:再次选中取消、visualMap 落选门控与交互快路径(2026-11-01)
151
+
152
+ - **需求来源**:根目录 `修改.txt` 三条:① 新增取消选中开关,默认关闭,单击、双击、Ctrl 先选中的路径都能再次操作取消;② 继续优化交互性能;③ `visualMap` 落选后应与热力图 / 网架联动,可选择消失对应网架或对应热力。按用户补充「不考虑分组详情」,本轮不扩展分组详情查询。
153
+ - **toggleSelect**:顶层 `options.toggleSelect` 缺省 `false`,`create.js` 透传引擎,`updateOptions` 可运行时切换。单击模式下第二次普通单击已选要素取反;`selectTrigger: 'dblClick'` 下由第二下取反、再次双击取消;Ctrl / ⌘ 先选中后再普通单击也取消。双击每轮只取反一次,不改变普通 `onClick` / `onDblClick` 的派发顺序;取反时 `onClick.action.type` 与 `onSelectChange.action.type` 都是 `toggleSelect`。
154
+ - **outOfRange**:`visualMap.outOfRange` 缺省 `'heatmap'`,只退出同一 `target` / `field` 的热力、恢复普通样式;`'network'` 额外隐藏落选节点、独立线路或整条通道成员,并从拾取与包围盒消失;`'none'` 不参与内置门控,只保留 `onChange`。`network` 的 `channel` 按声明收集全部成员回线,`line` 不误伤通道回线;缺值与非数值不参与隐藏。三种模式都不改数据、筛选、选中集或分组声明。图例状态、读数与 `onChange` 载荷都带 `outOfRange`。
155
+ - **性能**:引擎把筛选基线隐藏与 visualMap 视觉隐藏分成两套集合,解析时取并集;`network` 隐藏集合不变时 `setVisualMapState()` 返回 `hiddenChanged: false`,不重建场景。点 / 线热力样式缓存键分开,图例只影响节点时不再重算线路那一半;通道成员收集按声明一次完成。鹰眼图在 `network` 下同步隐藏,即使显式配置 `minimap.heatmap` 也不遮挡该语义。
156
+ - **Demo、测试与文档**:Demo 增加 `toggleSelect` 开关与落选值下拉;`selftest-select` 新增 5 条覆盖普通、双击、Ctrl、事件动作与关闭态,`selftest-features` 新增 8 条覆盖三种 `outOfRange`、节点 / 独立线路 / 通道、数据与筛选不变、隐藏集合快路径与鹰眼图同步。性能页的标签稳态用例改用 `progressiveInit: false` + `labelOptimize: true` 并显式等待 `isLayoutReady()`,避免锚点视图因发散渲染未完成而把第七轮首次真实排版误记成整屏重量。手册 03 / 08 / 13 / 14、`docs/GisView.md`、组件 README、API 索引、本页与 15.111 同步。
157
+ - **核心文件**:`src/gis-view/engine.js`、`create.js`、`heatmap.js`、`visual-map.js`、`update-policy.js`、`types.d.ts`;`docs/manual/03` / `08` / `13` / `14`、`docs/GisView.md`、`src/gis-view/README.md`、Demo 组合式函数与面板、`selftest-select.html` / `selftest-features.html` / `selftest-perf.html`、`docs/AI对话汇总.md`、本页与 15.111。
158
+ - **验证**:`npx tsc --noEmit`、`npm run check:docs`、`npm run build`、`git diff --check` 通过;API 索引为 283 个实例成员(278 方法 + 5 属性)/ 107 options / 275 数据字段;串行自测 `selftest-select` **107/0**、`selftest-features` **836/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-perf` **197/0**。
159
+
160
+ ## 五、上两增量:热力密度几何隔离、线路热力连续与 visualMap 运行时门控(2026-11-01)
161
+
162
+ - **需求来源**:根目录 `修改.txt` 三条:① 开启热力图后平移 / 缩放时仍有部分线路热力先消失再出现;② 开启热力图后背景也跟着放大缩小;③ `visualMap` 交互没有效果,应参考 ECharts 的交互直接作用于热力表现。
163
+ - **背景缩放根因**:密度场有独立的 `heatDensityBuffer`,但 `drawImageQuad()` 仍默认绑定背景图片的 `imageVao`,密度四边形一变就按图片几何缩放。现在新增 `heatDensityVao`,密度场拥有自己的四边形与 VAO;背景图片仍用 `imageVao`,两者销毁时分别释放。
164
+ - **线路热力连续**:`engine.js` 不再按 `interacting || cameraMoving` 把线路热力切到无光晕 / 细线路径。普通或自动浅底配置固定走 `drawHeatLineBatch()` 一笔合并核与光晕;加法混合或实例属性槽位不匹配时固定走两遍 `drawLineHeatGlow()`。自动画质降档也不会关闭线路热力,节点光晕仍可在交互期让路。
165
+ - **visualMap 门控链路**:`visual-map.js` 的 `visualStateSnapshot()` 只输出 `type` / `target` / `field` / `selected` / `range` / 选中的 `pieces`,同一状态不重复通知;`create.js` 保存首帧状态并在引擎创建后以 `refresh: false` 灌入,之后调用引擎内部 `setVisualMapState()`。`heatmap.js` 的 `visualStateAllows()` 只在 `target` 与 `field` 都匹配时门控,避免误伤独立图例或另一类要素;落选值回到普通样式,不删除数据、不触发筛选。默认继承主图热力的鹰眼图使用同一状态并随选区刷新,显式 `minimap.heatmap` 不跟随。
166
+ - **交互边界**:分段空选择关闭对应热力,区间端点为闭区间,分段按归一化后的开闭端点判断;受控写回只更新选区、不发 `onChange`。选区变化只重算热力样式、光晕和密度权重,几何、背景与标签不重排;没有新增公开实例成员 / options / 数据字段。
167
+ - **回归与文档**:`selftest-features` 新增分段取消 / 受控选择、连续尺区间外的热力门控、密度场重采样、继承鹰眼图同选区与显式 `minimap.heatmap` 独立断言;`selftest-perf` 新增图片背景 + 密度场范围断言、逐条线路中点采样和加法混合管线断言,并把测试等待改成先兑现渲染帧再等图片解码,避免静止画面 `whenRendered()` 挂起。手册 03 / 11 / 13 / 14 / 15、`docs/GisView.md`、类型注释、组件 README、Demo 提示与 API 索引同步。
168
+ - **核心文件**:`src/gis-view/engine.js`、`heatmap.js`、`visual-map.js`、`create.js`、`types.d.ts`、`src/gis-view/README.md`;`docs/manual/03` / `11` / `13` / `15`、`docs/GisView.md`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`panels/StylePanels.vue`、`docs/steps/selftest-features.html` / `selftest-perf.html`、本页与 15.110。
169
+ - **验证**:`npx tsc --noEmit`、`node --check`、`npm run check:docs`、`npm run build`、`git diff --check` 通过;串行自测 `selftest-features` **828/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-perf` **197/0**。性能页此前一次完整运行曾出现既有的标签布局读数断言失败(1313 次),最终复跑未再出现,与本轮改动没有调用关系。
170
+
171
+ ## 六、上三增量:线路热力交互连续显示与 visualMap 自定义交互(2026-10-31)
172
+
173
+ - **需求来源**:根目录 `修改.txt` 三条:① 开启热力图后平移 / 缩放时线路热力先消失再出现;② 继续优化开启热力图后的交互性能;③ 图例支持完全自定义与交互,参考 ECharts `visualMap`。
174
+ - **热力消失根因**:相机移动重铺线路实例时,`buildLineInstances()` 没有写回 `heat`,重铺后强度归零;`LINE_VERTEX_SHADER` 又把 `a_corner.y` 在顶点阶段取了绝对值,插值后整块四边形恒为 1,光晕衰减失效。修复为补 `heat: line.heat ?? 0`,顶点保留带符号 `v_edge`,片元再取 `abs()`。
175
+ - **合并线与性能**:交互 / 相机运动帧由 `HEAT_LINE_FRAGMENT_SHADER` + `heatLineProgram` 一笔同时画本色核与外侧光晕,不增加 draw call;预乘普通混合避免重叠线推白,停稳后仍按配置的 `glow.blend` 两遍绘制。密度场四边形改静态 `heatDensityBuffer`,运动期跳过重烤、停稳补烤;节点光晕交互期让路,线路热力保持连续。
176
+ - **visualMap 交互与自定义**:新增 `interactive`、`selectedMode`、`selected`、`range`、`calculable`、`onChange`、`render(context)`。分段支持点击 / Enter / Space 单选与多选,连续尺支持区间遮罩、双滑块、拖动与键盘;`onChange` 走 rAF 合帧并带 `source` / `reason` / `originalEvent` / `rangeRatios` 等载荷,受控更新不回声。`render(context)` 可返回 DOM / DocumentFragment / HTML 或直接写 `context.body`,复用 `setSelection` / `setRange` / `clearSelection` / `emitChange`;`getVisualMap()` 返回交互状态、选择、区间与比例。
177
+ - **公开面与核心文件**:没有新增实例成员 / options / 数据字段,保持 283 个实例成员(278 方法 + 5 属性)/ 106 options / 274 数据字段。核心文件为 `src/gis-view/shaders.js`、`engine.js`、`heatmap.js`、`visual-map.js`、`create.js`、`types.d.ts`、`gis-view.css`、Demo 组合式函数与样式面板、手册 03 / 11 / 13 / 15 / 16 / 17 / 18、`docs/GisView.md`、`src/gis-view/README.md`、四个自测页、本页与 15.109。
178
+ - **验证**:`node --check` 覆盖着色器 / 引擎 / 热力图 / 图例 / 组件入口 / Demo;`npx tsc --noEmit` 0 错;`node docs/steps/gen-api-index.mjs` 与 `--check`、`npm run check:docs`(283 / 278 / 5 / 106 / 274)、`npm run build`、`git diff --check` 通过;串行自测 `selftest-features` **823/0**、`selftest-perf` **195/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**。
179
+
180
+ ## 七、上四增量:visualMap 图例与图例专用快路径(2026-10-31)
181
+
182
+ - **需求来源**:根目录 `修改.txt` 两条:① 参考 ECharts `visualMap`,增加类似图例并结合 ruler 样式;② 继续优化组件性能。
183
+ - **图例模型**:新增 `src/gis-view/visual-map.js` 与 `options.visualMap`。`ruler` / `continuous` 为连续渐变尺 + 刻度,`piecewise` 为分段色块;支持 `pieces` 的 `gte` / `gt` / `lte` / `lt` / `min` / `max`,以及显式 `domain` / 单端 `min` / `max`、`colors` / `stops` / `opacity`、标题 / 单位 / formatter、方向 / 定位 / 尺寸 / 外部容器 / class / 内联样式。默认继承 `heatmap` 的 target / field / domain / colors / stops / opacity,没有热力图时按自己的 `field` 扫独立值域。
184
+ - **零挂载与读数**:不配 / `null` / `enabled: false` 不挂节点;`getVisualMapElement()` 返回根节点,`getVisualMap()` 返回类型、目标、字段、值域、色带与刻度 / 分段。图例默认 `pointer-events: none`,不参与拾取。
185
+ - **性能快路径**:`heatmap.js` 导出 `createHeatmapRamp()`,图例与画布共用同一套色带插值;更新走 rAF 合帧与渲染签名缓存,同签名零 DOM 写入。数据变化由 `markDataDirty()` 合并到下一帧,图例侧自动值域在本次配置生命周期内复用自身解析缓存;显式 `domain` 或两端都写死的 `min` / `max` 跳过数据扫描。`updateOptions({ visualMap })` 单独走覆盖层快路径,绕过引擎场景、鹰眼图与标签重排;性能页先等待字体队列稳定再计量稳态重排,不放宽已有断言。
186
+ - **Demo 与文档**:热力图面板增加图例开关与连续尺 / 分段选择,Demo 默认跟随热力图字段与色带。手册 03 / 11 / 13 / 15 / 16 / 17 / 18、组件 README、文档中心与自测页同步;实例成员 281 → **283**(方法 276 → **278**,属性仍 5),options 105 → **106**,数据字段 273 → **274**,分组仍 16。
187
+ - **核心文件**:`src/gis-view/visual-map.js`、`heatmap.js`、`create.js`、`gis-view.css`、`types.d.ts`、`src/gis-view/README.md`;`docs/manual/03` / `11` / `13` / `15` / `16` / `17` / `18`、`docs/index.html`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`panels/StylePanels.vue`、`docs/steps/selftest-features.html` / `selftest-perf.html` / `selftest-demos.html` / `selftest-docs.html`、API 索引、本页与 15.108。
188
+ - **验证**:`npx tsc --noEmit`、`node --check`、`node docs/steps/gen-api-index.mjs`、`gen-api-index.mjs --check`、`npm run check:docs`(283 / 278 / 5 / 106 / 274)、`npm run build`、`git diff --check` 通过;浏览器自测 `selftest-features` **808/0**、`selftest-perf` **190/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-demo` **133/0**。
189
+
190
+ ## 八、上五增量:fitSpacing.minDistance 精确落位与指定节点组间距(2026-10-30)
133
191
 
134
192
  - **需求来源**:根目录 `修改.txt` 三条:① `minDistance` 一旦设置就必须精确显示为该屏幕距离,不能因为初始值或内部限制只能变大;② 新增方法,传一组节点返回整组的 `minDistance` / `maxDistance`;③ 文档写明距离如何由坐标与相机比例换算。
135
193
  - **根因与修复**:`engine.js` 的 `fitSpacingAdjustment()` 原先把 `minDistance / 最近世界距离` 与普通适应比例取 `Math.max`,再用 `maxZoom` 截断,所以目标比例更小时不生效。现在 `minDistance` 直接作为精确目标比例,可放大也可缩小;`maxZoom` 仅兼容保留,最终只由 `minScale` / `maxScale` 夹取,相机中心仍沿用普通包围盒中心。
@@ -138,7 +196,7 @@
138
196
  - **公开面与核心文件**:实例成员 280 → **281**(方法 275 → **276**),options 105、数据字段 273、分组 16 不变。核心文件为 `src/gis-view/engine.js`、`create.js`、`types.d.ts`、`src/gis-view/README.md`,以及手册 03 / 14 / 16 / 17 / 18、Demo 面板、`selftest-scale.html`、`selftest-docs.html`、`selftest-demos.html`、API 索引、本页与 15.107。
139
197
  - **验证**:`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs`、`npm run check:docs`(281 / 276 / 105 / 273)、`npm run build`、`git diff --check` 通过;浏览器串行自测 `selftest-features` **794/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-demo` **133/0**;`selftest-scale` **126/2**,新增断言全过,两条失败仍是既有筛选回调时序(`onFilter 0 条`)。
140
198
 
141
- ## 四、上一增量:背景文字同帧刷新与 fitSpacing.minDistance 上限修复(2026-10-30)
199
+ ## 九、上六增量:背景文字同帧刷新与 fitSpacing.minDistance 上限修复(2026-10-30)
142
200
 
143
201
  - **需求来源**:根目录 `问题.txt` 两条:① 拖动 GeoJSON 背景仍有晃动,文字尤其明显;② `fitSpacing.minDistance` 有时怎么设置都不生效,`maxDistance` 正常,像是有内部强制限制。
144
202
  - **背景文字晃动**:`overlay.setBackgroundLabels()` 会把新的区域文字排到下一帧,而内置背景编辑器的 `applyBackground()` 已经同步重画了 WebGL 底图和编辑框,两者相差一帧。`refreshBackgroundLabels()` 现在立即排版并取消待执行的 rAF;编辑器的 `applyBackground()` 在 `updateBackground()` + `refresh({ reflow: false })` 后同步调用它,底图、编辑框、区域文字同任务提交。
@@ -147,7 +205,7 @@
147
205
  - **核心文件**:`src/gis-view/engine.js`、`overlay.js`、`create.js`、`types.d.ts`、`README.md`;`docs/manual/03` / `14`、`docs/from0/15`、`docs/demos/api-index.js`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`docs/steps/selftest-features.html`、`selftest-scale.html`、`selftest-demo.html`、`docs/AI对话汇总.md`、本章节、15.106。
148
206
  - **验证**:`npx tsc --noEmit` 0 错;`node docs/steps/gen-api-index.mjs` 更新索引;`npm run check:docs` 全绿(280 个实例成员 / 105 个 options / 273 个数据字段);`npm run build` 通过;`git diff --check` 通过。浏览器串行自测:`selftest-features` **794/0**、`selftest-demos` **441/0**、`selftest-docs` **139/0**、`selftest-demo` **133/0**;`selftest-scale` **121 通过 / 2 失败**,新增的默认上限断言通过,剩余两条仍是既有筛选回调时序(`onFilter 0 条`)。
149
207
 
150
- ## 五、上两增量:内置背景编辑器与旋转按钮命中修复(2026-10-30)
208
+ ## 十、上七增量:内置背景编辑器与旋转按钮命中修复(2026-10-30)
151
209
 
152
210
  - **需求来源**:根目录 `修改.txt` 两条:① 旋转按钮始终不旋转;② 将整块背景编辑模式内置,通过方法开启与配置,不再由 Demo 纯手写。
153
211
  - **旋转按钮根因**:旧编辑层 `.bg-edit-layer` 为 `pointer-events: none`,缩放手柄和轮廓单独恢复 `auto`,但旋转按钮漏了;内置编辑器的旋转按钮显式 `pointer-events: auto`,`selftest-demos` 通过 `document.elementFromPoint()` 验证真实命中后再拖动旋转。
@@ -158,7 +216,7 @@
158
216
  - **核心文件**:`src/gis-view/background-editor.js`(新增)、`gis-view.css`、`create.js`、`types.d.ts`;`docs/demos/BackgroundDemo.vue`、`demos.js`、`docs/manual/03` / `14` / `16` / `17` / `18` / `21`、`docs/internals/14`、`docs/steps/selftest-demos.html`、`selftest-features.html`、`selftest-docs.html`、`docs/AI对话汇总.md`、本章节、15.105。
159
217
  - **验证**:`npx tsc --noEmit` 0 错;`node docs/steps/gen-api-index.mjs` 更新索引;`npm run check:docs` 全绿(280 个实例成员 / 105 个 options / 273 个数据字段);`npm run build` 通过;`git diff --check` 通过。浏览器串行自测:`selftest-features.html` **793/0**、`selftest-demos.html` **441/0**、`selftest-docs.html` **139/0**。
160
218
 
161
- ## 六、上三轮:背景编辑 4 / 8 / 9 点、旋转开关与可定制编辑框(2026-10-30)
219
+ ## 十一、上八增量:背景编辑 4 / 8 / 9 点、旋转开关与可定制编辑框(2026-10-30)
162
220
 
163
221
  - **需求来源**:根目录 `修改.txt` 五条:① 只有开启旋转时才出现旋转按钮;② 取消宽高锁定后从四角编辑改成常见八点,开启旋转后变成九点,并考虑背景旋转角;③ 背景编辑框样式支持自定义;④ 修复移动背景图的轻微晃动;⑤ 全部在 demo 中体现。
164
222
  - **编辑点与旋转**:`BackgroundDemo.vue` 锁定比例时显示四角等比缩放;解锁后增加四边中点,共八个缩放手柄;旋转开关独立控制顶部旋转点与连线,只有开启时才从八点变成九点。关闭旋转仍保留当前角度和八个缩放手柄。
@@ -169,7 +227,7 @@
169
227
  - **核心文件**:`docs/demos/BackgroundDemo.vue`、`docs/demos/demos.js`、`docs/manual/03-配置项.md`、`docs/manual/14-视图与筛选.md`、`docs/manual/21-说明与常见问题.md`、`docs/steps/selftest-demos.html`、`docs/AI对话汇总.md`、本章节、15.104。
170
228
  - **验证**:`npx tsc --noEmit` 0 错;`npm run check:docs` 全绿(276 个实例成员 / 105 个 options / 273 个数据字段);`npm run build` 通过(仅既有大 chunk 提示);`git diff --check` 通过。浏览器串行自测:`selftest-features.html` **786/0**、`selftest-demos.html` **440/0**、`selftest-docs.html` **139/0**。
171
229
 
172
- ## 七、上四轮:背景移动 / 旋转、背景编辑模式与网架整体显隐(2026-10-30)
230
+ ## 十二、上九增量:背景移动 / 旋转、背景编辑模式与网架整体显隐(2026-10-30)
173
231
 
174
232
  - **需求来源**:根目录 `修改.txt` 两条:背景可移动、可旋转;调整背景时网架不能拖拽 / 点击等操作,但可与背景整体缩放,相当于背景编辑模式;Demo 明显有问题。同日上一增量(15.102)已补背景添加、四角调整与网架显隐 / 透明度,本轮补齐移动、旋转、编辑模式并修正 Demo。
175
233
  - **背景能力**:`geoJsonStyle.bounds` 负责独立缩放 / 平移到目标世界矩形,新增 `geoJsonStyle.rotation` 绕目标矩形中心顺时针旋转;所有解析几何、区域范围、重心与区域文字一起变换,`rawBounds` 保持原始坐标,`bounds` 为旋转后的轴对齐外框。图片用旋转后的 `image.corners` 表达,不改原始数据。
@@ -179,7 +237,7 @@
179
237
  - **核心文件**:`src/gis-view/engine.js`、`background.js`、`create.js`、`overlay.js`、`update-policy.js`、`types.d.ts`;`docs/demos/BackgroundDemo.vue`、`demos.js`、`docs/demos/api-index.js`、`docs/manual/03` / `14` / `16` / `18` / `21`、`docs/steps/selftest-features.html`、`selftest-demos.html`、`selftest-docs.html`、`docs/AI对话汇总.md`、本章节、15.102 / 15.103。
180
238
  - **验证**:`npx tsc --noEmit` 0 错;`node docs/steps/gen-api-index.mjs` 更新索引;`npm run check:docs` 全绿(276 个实例成员 / 105 个 options / 273 个数据字段);`npm run build` 通过(仅既有大 chunk 提示);`git diff --check` 通过。浏览器串行自测:`selftest-features.html` **786/0**、`selftest-demos.html` **433/0**、`selftest-docs.html` **139/0**。
181
239
 
182
- ## 八、上五轮:交互样式优先级回归、单 / 多要素样式 Demo 与详情查询(2026-10-30)
240
+ ## 十三、上十增量:交互样式优先级回归、单 / 多要素样式 Demo 与详情查询(2026-10-30)
183
241
 
184
242
  - **需求来源**:根目录 `修改.txt` 三条:① 选中 / 框选 / 多选 / 级联等交互颜色始终最高,不受规则束缚;② 增加修改单个或多个节点 / 线路样式的 demo;③ 查询单个或多个节点、线路、通道详情的写法。用户补充「不考虑分组详情」,因此本轮不扩展分组查询。
185
243
  - **交互优先级审计**:核对 `point.js` / `line.js` 的状态样式取值顺序,并确认 `applyPointNarrowFast` / `applyLineNarrowFast` 只在无规则、无热力图且规则输入未变时启用,不会绕过交互层。`selftest-features` 新增单选、动态 override 规则、多选节点 / 线路、框选节点 / 线路与级联共 7 条断言;线路框选仍走 `lineSelectStyle`,没有新增公开选项。
@@ -188,7 +246,7 @@
188
246
  - **核心文件**:`docs/demos/StyleDemo.vue`、`docs/demos/demos.js`、`docs/manual/11-样式与规则.md`、`docs/manual/18-逐方法示例.md`、`docs/steps/selftest-features.html`、`docs/steps/selftest-demos.html`、`docs/AI对话汇总.md`、本章节、15.101。
189
247
  - **验证**:`npx tsc --noEmit`、`npm run check:docs`(276 个实例成员 / 102 个 options / 270 个数据字段)、`npm run build`、`git diff --check` 通过;`selftest-features` **778/0**、`selftest-demos` **415/0**、`selftest-docs` **138/0**。未新增公开 API / options / 数据字段。
190
248
 
191
- ## 九、上六轮:规则优先级分层、单要素样式说明与解析性能(2026-10-30)
249
+ ## 十四、上十一增量:规则优先级分层、单要素样式说明与解析性能(2026-10-30)
192
250
 
193
251
  - **需求来源**:根目录 `修改.txt` 四条 —— ① 规则样式始终高于外层 `pointStyle` / `lineStyle`,但默认低于要素自身样式;② 单条规则可设置 `override: true`,压过要素自身样式;③ 说明如何修改单个节点 / 单条线路的颜色、尺寸、图标等样式;④ 继续优化组件性能。
194
252
  - **优先级口径**:状态样式 / 热力图 > override 规则 > 要素自身样式 > 普通规则 > 外层 `pointStyle` / `lineStyle` > 默认值。普通规则只补要素自身没写的字段,但始终高于外层样式;override 规则写了的字段压过要素自身,未写字段继续回落;同一层后命中的规则覆盖先命中的规则。状态样式与热力图保持最高。
@@ -198,7 +256,7 @@
198
256
  - **核心文件**:`src/gis-view/rules.js`、`point.js`、`line.js`、`engine.js`、`create.js`、`types.d.ts`;手册 11 及 02 / 03 / 07 / 09 / 12 / 13 / 14 / 16 / 17 / 18 / 19 / 20 / 21、格式 02 / 03、internals 10 / 13 / 17 / 18 / 15.100、from0 06、教学页、`src/gis-view/README.md`、`StyleDemo.vue`、`docs/demos/api-index.js`、`docs/AI对话汇总.md`、本章节。
199
257
  - **验证**:`npx tsc --noEmit`、`npm run check:docs`(276 / 102 / 270)、`node docs/steps/gen-api-index.mjs`、`npm run build`、`git diff --check` 通过;`selftest-features` 771/0(新增 11 条优先级、override、状态样式、`updatePoint` / `updateLine` 断言),actions 96/0、data 103/0、decoration 75/0、demo 133/0、demos 407/0、docs 138/0、effects 96/0、full 94/0、labels 178/0、select 102/0、selftest 19/0。`selftest-perf` 186/1(既有标签布局读数量测)、`selftest-scale` 120/2(既有筛选回调时序 `onFilter 0 条`),单页重跑仍复现,与本轮样式链无关。
200
258
 
201
- ## 十、上七轮:updatePoint 快路径、id 索引拆分与插件生命周期(2026-10-29)
259
+ ## 十五、上十二增量:updatePoint 快路径、id 索引拆分与插件生命周期(2026-10-29)
202
260
 
203
261
  - **需求来源**:根目录 `修改.txt` 两条:① 继续优化组件性能,包括交互、方法调用等,允许大改;② 提高组件可扩展性和后续可操作性。
204
262
  - **updatePoint 快路径**:只有坐标 / id 变化才收集跟随线路,只有节点外框尺寸变化才重排锚定通道;改名称、颜色等业务字段直接补单点槽位,不再扫线路、重排通道或刷新拐点批次。id 改名时先用旧对象解析旧线路绑定,再用新坐标补几何。
@@ -208,7 +266,7 @@
208
266
  - **核心文件**:`src/gis-view/create.js`、`engine.js`、`types.d.ts`;`docs/manual/03` / `15` / `16` / `17` / `18` / `20`、`docs/demos/api-index.js`、`docs/steps/selftest-features.html`、`docs/AI对话汇总.md`、本章节。
209
267
  - **验证**:`npx tsc --noEmit`、`npm run check:docs`(276 / 102 / 270)、`node docs/steps/gen-api-index.mjs --check`、`npm run build`、`git diff --check` 通过;`selftest-select` 102/0、`selftest-demos` 407/0、`selftest-features` 760/0、`selftest-docs` 138/0、`selftest-perf` 187/0。
210
268
 
211
- ## 十一、上八轮:div 保留框跟随、通道单回线显隐与拾取优化(2026-10-29)
269
+ ## 十六、上十三增量:div 保留框跟随、通道单回线显隐与拾取优化(2026-10-29)
212
270
 
213
271
  - **需求来源**:根目录 `修改.txt` 四条:① 框选后保留选框,并支持拖动整框平移选中节点及关联线路 / 通道;② 框选框支持自定义边框、DOM 渲染与类名;③ 节点、线路、通道、分组支持单个 / 批量隐藏与恢复;④ 隐藏线路时可保留原回线位置或让剩余回线重新居中。
214
272
  - **本轮续修来源**:根目录 `修改.txt` 三条:① div 保留框移动地图时跟随;② 通道 demo 展示隐藏通道内指定线路;③ 继续优化性能。
@@ -218,7 +276,7 @@
218
276
  - **核心文件**:`src/gis-view/engine.js`、`create.js`、`types.d.ts`、`update-policy.js`、`gis-view.css`;`docs/manual/03` / `08` / `09` / `16` / `17` / `18` / `20`、`docs/internals/18`、`ChannelDemo.vue`、`demos.js`、`gis-view-demo` 面板、`docs/steps/selftest-select.html`、`selftest-demos.html`、`selftest-features.html`、`selftest-docs.html`、`selftest-perf.html`、`docs/demos/api-index.js`、`docs/AI对话汇总.md`、本章节。
219
277
  - **验证**:`npx tsc --noEmit`、`npm run check:docs`(276 个实例成员 / 102 个 options / 270 个数据字段)、`node docs/steps/gen-api-index.mjs --check`、`npm run build`(仅有既有大 chunk 提示)与 `git diff --check` 通过;`selftest-select` 102/0、`selftest-demos` 407/0、`selftest-features` 752/0、`selftest-docs` 138/0、`selftest-perf` 187/0。10 万点 / 10 万线基准连续 3 次已记录在手册 20 与 internals 18,拾取保持亚毫秒级,平移 / 刷新受无头环境抖动影响。
220
278
 
221
- ## 十二、怎么自己复查
279
+ ## 十七、怎么自己复查
222
280
 
223
281
  ### 1. 先看本次工作区改了什么
224
282
 
@@ -265,4 +323,4 @@ node scripts/run-selftests.mjs selftest-select.html
265
323
  - 组件本体:34 个会话
266
324
  - 选型与立项:2 个会话
267
325
  - 宿主旁支:3 个会话
268
- - 时间跨度:2026-09-15 ~ 2026-10-30
326
+ - 时间跨度:2026-09-15 ~ 2026-10-31
@@ -7,8 +7,8 @@
7
7
  * 源码或文档改过之后重跑一遍;`node docs/steps/check-doc-coverage.mjs` 会对账。
8
8
  */
9
9
 
10
- /** { members: 281, methods: 276, properties: 5, options: 105, sections: 16 } */
11
- export const API_SUMMARY = {"members":281,"methods":276,"properties":5,"options":105,"sections":16}
10
+ /** { members: 283, methods: 278, properties: 5, options: 107, sections: 16 } */
11
+ export const API_SUMMARY = {"members":283,"methods":278,"properties":5,"options":107,"sections":16}
12
12
 
13
13
  /** 实例成员,按 docs/GisView.md「参数速查」的分组排 */
14
14
  export const API_SECTIONS = [
@@ -75,6 +75,8 @@ export const API_SECTIONS = [
75
75
  { name: "getViewRect", kind: "method", params: "无", returns: "GisViewBounds", doc: "当前可视范围的世界坐标矩形;自建缩略图 / 坐标读数用它换算视口框,内置鹰眼图见「鹰眼图」", examples: [{"group":"相机与视图","code":"// getBounds() / getViewRect() / getViewport():数据范围 / 视口世界矩形 / 画布尺寸读数\nconst dataBounds = view.getBounds()\nconst viewRect = view.getViewRect()\nconst { cssWidth, cssHeight, pixelRatio } = view.getViewport()\n","from":"header"}] },
76
76
  { name: "isLayoutReady", kind: "method", params: "无", returns: "boolean", doc: "大数据发散渲染(progressiveInit)是否已经铺完;没铺完时标签与拾取只看得到已经画出去的那部分", examples: [{"group":"相机与视图","code":"// isLayoutReady():容器量到尺寸、首批布局完成没有\nconst layoutReady = view.isLayoutReady()\n","from":"header"}] },
77
77
  { name: "getMinimapElement", kind: "method", params: "无", returns: "HTMLElement | null 鹰眼图根节点(没配 minimap 时为 null);外部整图拖动 / 自定义手势用它,配合 minimap.container 可挂到外部宿主", doc: "鹰眼图根节点(没配 minimap 时为 null):接整图拖动或自定义手势;配合 minimap.container 挂到外部宿主时拿到的仍是同一根节点", examples: [{"group":"相机与视图","code":"// getMinimapElement():拿鹰眼图根节点做整图拖动 / 自定义手势(没配 minimap 时为 null)\nconst minimapElement = view.getMinimapElement()\n","from":"header"}] },
78
+ { name: "getVisualMapElement", kind: "method", params: "无", returns: "HTMLElement | null 内置图例根节点(没配 visualMap 或 enabled: false 时为 null);挂外部事件或自定义样式从这里拿。interactive: true 时根节点已可直接点选 / 拖动,内置交互优先用 onChange", doc: "内置图例的根节点 / 当前读数:根节点在没配 visualMap 或 enabled: false 时为 null;读数含 type / target / field / domain / colors、交互态 interactive / selectedMode / calculable / selected / range / rangeRatios 与 ticks / pieces,没配时为 null。分段点选 / 区间拖动走 visualMap.onChange,render(context) 可完全自定义;只改图例不会触发引擎场景或标签重排,见「图例(visualMap)」", examples: [{"group":"相机与视图","code":"// getVisualMapElement() / getVisualMap():内置图例的根节点与当前读数(没配 visualMap 时为 null)\nconst visualMapElement = view.getVisualMapElement()\nconst visualMap = view.getVisualMap()","from":"header"}] },
79
+ { name: "getVisualMap", kind: "method", params: "无", returns: "GisViewVisualMapReadout | null 当前图例读数:type / target / field / domain / colors / orient / title / unit、交互态 interactive / selectedMode / calculable / selected / range / rangeRatios 与 ticks / pieces;没配时为 null,调用前会先落下一帧挂起的重画", doc: "内置图例的根节点 / 当前读数:根节点在没配 visualMap 或 enabled: false 时为 null;读数含 type / target / field / domain / colors、交互态 interactive / selectedMode / calculable / selected / range / rangeRatios 与 ticks / pieces,没配时为 null。分段点选 / 区间拖动走 visualMap.onChange,render(context) 可完全自定义;只改图例不会触发引擎场景或标签重排,见「图例(visualMap)」", examples: [{"group":"相机与视图","code":"// getVisualMapElement() / getVisualMap():内置图例的根节点与当前读数(没配 visualMap 时为 null)\nconst visualMapElement = view.getVisualMapElement()\nconst visualMap = view.getVisualMap()","from":"header"}] },
78
80
  { name: "getMinimapZoom", kind: "method", params: "无", returns: "number", doc: "读 / 写鹰眼图自身的倍数:set 夹在 minimap.minZoom ~ maxZoom 之间,zoomMinimapBy 以画布 CSS 像素 origin 为锚点缩放(缺省小图中心),没配 minimap 时是空操作", examples: [{"group":"相机与视图","code":"// getMinimapZoom() / setMinimapZoom(zoom) / zoomMinimapBy(factor, origin?):鹰眼图缩放\nview.setMinimapZoom(4)\nview.zoomMinimapBy(1.25)\nconst minimapZoom = view.getMinimapZoom()\n","from":"header"}] },
79
81
  { name: "setMinimapZoom", kind: "method", params: "zoom: number 鹰眼图的目标倍数(被 minimap.minZoom / maxZoom 夹住)", returns: "this", doc: "读 / 写鹰眼图自身的倍数:set 夹在 minimap.minZoom ~ maxZoom 之间,zoomMinimapBy 以画布 CSS 像素 origin 为锚点缩放(缺省小图中心),没配 minimap 时是空操作", examples: [{"group":"相机与视图","code":"// getMinimapZoom() / setMinimapZoom(zoom) / zoomMinimapBy(factor, origin?):鹰眼图缩放\nview.setMinimapZoom(4)\nview.zoomMinimapBy(1.25)\nconst minimapZoom = view.getMinimapZoom()\n","from":"header"}] },
80
82
  { name: "zoomMinimapBy", kind: "method", params: "factor: number 倍数;origin?: [x, y] 以小图里的哪个点为中心(缺省小图中心)", returns: "this", doc: "读 / 写鹰眼图自身的倍数:set 夹在 minimap.minZoom ~ maxZoom 之间,zoomMinimapBy 以画布 CSS 像素 origin 为锚点缩放(缺省小图中心),没配 minimap 时是空操作", examples: [{"group":"相机与视图","code":"// getMinimapZoom() / setMinimapZoom(zoom) / zoomMinimapBy(factor, origin?):鹰眼图缩放\nview.setMinimapZoom(4)\nview.zoomMinimapBy(1.25)\nconst minimapZoom = view.getMinimapZoom()\n","from":"header"}] },
@@ -400,6 +402,7 @@ export const API_OPTIONS = [
400
402
  { name: "pointRules", type: "GisViewPointRule[] / GisViewLineRule[]", defaultValue: "[]", doc: "批量样式规则:按属性给点 / 线批量配色、改大小、换符号,见「批量样式规则」" },
401
403
  { name: "lineRules", type: "GisViewPointRule[] / GisViewLineRule[]", defaultValue: "[]", doc: "批量样式规则:按属性给点 / 线批量配色、改大小、换符号,见「批量样式规则」" },
402
404
  { name: "heatmap", type: "GisViewHeatmap | null", defaultValue: "无", doc: "热力图:按业务字段的数值到渐变色带上取颜色,并可按同一个值缩放节点大小 / 线宽,作用对象可选节点 / 线路 / 通道;不配(或 null)就是关的,见「热力图」" },
405
+ { name: "visualMap", type: "GisViewVisualMap | null", defaultValue: "无", doc: "图例:参考 ECharts visualMap,把热力图的色带画成带刻度的连续尺(ruler / continuous)或分段色块(piecewise)。不配 / null / enabled: false 时零 DOM;默认跟随 heatmap 的字段、自动值域与颜色,也能独立给字段 / 值域 / 颜色 / 外部容器。不写 target 时展示值域取第一类有数值的启用目标,交互门控覆盖 heatmap 的全部启用目标;显式写才限定为一类,见「图例(visualMap)」" },
403
406
  { name: "effects", type: "GisViewEffectsInput", defaultValue: "关", doc: "动画效果(全局缺省):线路上的跑动图标(line,ECharts lines.effect 那一类)与节点上的扩散涟漪(point,effectScatter 那一类),逐要素用 points[].effect / lines[].effect 覆盖;没配就是关的,但「只在数据里逐条配了 effect」的场景照样会动。false 或 { enabled: false } 是一处关掉(谁都别动);运行时有 updateOptions({ effects }) / getEffects() / getLineEffects(),见「动画效果(effects)」" },
404
407
  { name: "lineDirection", type: "GisViewLineDirectionInput", defaultValue: "关(null)", doc: "线路方向箭头(全局缺省):沿线摆一串静态箭头,朝向跟着线路切向走(起点 / from 那一端 → 终点,reverse 指回上游),按弧长等分、缺省每条线只在中点一个;逐条线路用 lines[].direction 覆盖,写法与 effects 同构(true 用全局、对象逐字段覆盖、false / null 关掉),见「线路方向箭头(lineDirection)」" },
405
408
  { name: "prebake", type: "GisViewPrebakeOptions | true", defaultValue: "关", doc: "贴图符号预热:把「这次画面会出现什么」提前告诉组件 —— 两种写法:combos 逐组合(精确,getSymbolCombos() 收出来的那份)/ symbols × pointColors × sizes 与 lineColors × 线路动画图标 全排列(省事,颜色与尺寸由同一个字段决定时会多烤很多)—— 第一帧之前就烤好,画到它们时命中的是现成的贴图(省掉解码 + 光栅化那一下);组合数与数据量无关,不配就是从前那条按需路径。读数 getPrebake() / getSymbolCombos()、手动再烤一遍 runPrebake(),见「贴图符号预热(prebake)」" },
@@ -431,6 +434,7 @@ export const API_OPTIONS = [
431
434
  { name: "fitSpacing", type: "boolean | GisViewFitSpacingOptions", defaultValue: "关", doc: "适应视图的节点间距兜底:true 把最近节点中心距精确设为 24 CSS 像素;对象在 minDistance(精确屏距,可放大也可缩小)/ maxDistance(最远距离上限,只压低比例)中二选一,同时给出时只启用 maxDistance;maxZoom 仅为旧配置兼容保留,不再限制距离;只在首次默认适应与 fitView() 生效,远处孤立点允许落到视口外,见「适应视图的节点间距(fitSpacing)」" },
432
435
  { name: "boxSelect", type: "boolean", defaultValue: "false", doc: "是否允许按住框选快捷键(shortcuts.boxSelect,默认 Shift)拖动鼠标框选要素;缺省关,写 boxSelect: true 或 features: { boxSelect: true } 才开。框选默认只收节点,selectionKinds 可把线路 / 通道也纳入" },
433
436
  { name: "multiSelect", type: "boolean", defaultValue: "false", doc: "多选开关:打开后不用按修饰键,直接单击节点 / 线路就取反累加选中(与按住 shortcuts.multiSelect 点击同一套行为、同一个 multiSelectStyle;取反那一下不经过 onClick,onSelectChange.action.type 是 toggleSelect);缺省关,关着时多选走框选(boxSelect)与按住多选快捷键(默认 Ctrl / ⌘)。运行时 updateOptions({ multiSelect }) 切换只重画一帧、不重排场景" },
437
+ { name: "toggleSelect", type: "boolean", defaultValue: "false", doc: "再次选中即取消:打开后普通单击已选中的节点 / 线路 / 通道会取消,selectTrigger: 'dblClick' 下再次双击取消,Ctrl / ⌘ 先选中后再普通单击也取消;取反时 onClick.action.type 与 onSelectChange.action.type 都是 toggleSelect。缺省关,运行时 updateOptions({ toggleSelect }) 只重画一帧、不重排场景,见「选中与拐点」" },
434
438
  { name: "selectTrigger", type: "'click' | 'dblClick'", defaultValue: "'click'", doc: "选中触发方式:click 第一次单击就改选中集;dblClick 第一下只派发 onClick,等双击判定命中的第二下才改选中集,并同时派发 onClick 与 onDblClick。Ctrl / ⌘ 多选与 multiSelect 在双击模式下同样等第二下才取反。运行时走 updateOptions({ selectTrigger }),只重画一帧、不重排场景" },
435
439
  { name: "selectionKinds", type: "GisViewSelectionKindsInput", defaultValue: "无(框选只收节点;Ctrl 多选收节点 / 线路 / 通道)", doc: "框选与 Ctrl / 多选点击的类型过滤:'point' 节点、'line' 通道外的独立线路、'channel' 通道回线;另有 'lineEndpoints' / 'channelEndpoints',只在框选时要求线路 / 通道两端节点都在框内。可写数组任意组合,'all' / true 全开,false / null 全关。通道回线只归 channel 管,通道外的线路只归 line 管;通道回线仍按 channelSelectMode 摊开。不写时保留旧口径;普通单选与 select / selectFeatures 不受它限制。运行时走 updateOptions({ selectionKinds }),见「框选」与「选择类型过滤」" },
436
440
  { name: "selectionBoxStyle", type: "GisViewSelectionBoxStyle", defaultValue: "蓝底 0.16 透明 + 1px 蓝框", doc: "框选矩形的样式:fill / fillOpacity / stroke / strokeWidth,以及 DOM 渲染用的 render: 'div' / className / borderStyle / radius;canvas 模式不画线型与圆角,见「框选」" },
@@ -1248,3 +1248,59 @@
1248
1248
  letter-spacing: 0.02em;
1249
1249
  white-space: nowrap;
1250
1250
  }
1251
+
1252
+ /* visualMap 完全自定义渲染:图例根节点只负责定位,内容与交互全部由 render(context) 接管 */
1253
+ .gis-view-demo .demo-visual-map-custom {
1254
+ display: flex;
1255
+ flex-direction: column;
1256
+ gap: 7px;
1257
+ min-width: 190px;
1258
+ }
1259
+
1260
+ .gis-view-demo .demo-visual-map-custom__readout {
1261
+ color: #526b8d;
1262
+ font-size: 11px;
1263
+ font-variant-numeric: tabular-nums;
1264
+ }
1265
+
1266
+ .gis-view-demo .demo-visual-map-custom__actions {
1267
+ display: flex;
1268
+ flex-wrap: wrap;
1269
+ gap: 4px;
1270
+ }
1271
+
1272
+ .gis-view-demo .demo-visual-map-custom__piece {
1273
+ display: inline-flex;
1274
+ align-items: center;
1275
+ gap: 5px;
1276
+ margin: 0;
1277
+ padding: 3px 6px;
1278
+ border: 1px solid rgb(31 53 80 / 18%);
1279
+ border-radius: 4px;
1280
+ background: #fff;
1281
+ color: #1f3550;
1282
+ font: inherit;
1283
+ font-size: 11px;
1284
+ cursor: pointer;
1285
+ }
1286
+
1287
+ .gis-view-demo .demo-visual-map-custom__piece:hover {
1288
+ border-color: rgb(47 120 183 / 45%);
1289
+ background: rgb(47 120 183 / 8%);
1290
+ }
1291
+
1292
+ .gis-view-demo .demo-visual-map-custom__piece:focus-visible {
1293
+ outline: 2px solid rgb(47 120 183 / 55%);
1294
+ outline-offset: 1px;
1295
+ }
1296
+
1297
+ .gis-view-demo .demo-visual-map-custom__piece[aria-pressed='false'] {
1298
+ opacity: 0.46;
1299
+ }
1300
+
1301
+ .gis-view-demo .demo-visual-map-custom__swatch {
1302
+ width: 10px;
1303
+ height: 10px;
1304
+ flex: none;
1305
+ border-radius: 2px;
1306
+ }
@@ -21,7 +21,9 @@ const {
21
21
  heatmapDensityStyle, heatmapDensityLayer, heatmapDensityLevels, heatmapDensityRadius, heatmapDensityThreshold,
22
22
  heatmapDensityCore, heatmapDensityGamma, heatmapDensityWeight, heatmapDensityOpacity, heatmapGlow,
23
23
  heatmapGlowStrength, heatmapGlowLine, heatmapGlowPoint, heatmapGlowBlend, heatmapOpacityMin, heatmapOpacityMax,
24
- heatmapMinimap, heatmapFieldStats, applyZoomBase, labelEditId, newLabelPosition, newLabelPositions,
24
+ heatmapMinimap, heatmapFieldStats, visualMapEnabled, visualMapType, visualMapInteractive, visualMapCustom,
25
+ visualMapOutOfRange, VISUAL_MAP_OUT_OF_RANGE_MODES,
26
+ visualMapReadout, visualMapLastChange, applyZoomBase, labelEditId, newLabelPosition, newLabelPositions,
25
27
  labelEditContent, labelEditFontSize, labelEditColor, labelEditReadout, labelStateReadout, applyLabelEdit,
26
28
  resetLabelEdit, resetAllLabels, labelRows, labelListReadout, labelRoundTripReadout, pickLabelRow, addLabelHere,
27
29
  removeLabelHere, seedInitialLabels, roundTripLabels, saveLabelStates, restoreLabelStates, rerollHeatData,
@@ -33,6 +35,25 @@ const {
33
35
  <div v-show="activePanel === 'style-heat'" class="demo-panel-body">
34
36
  <div class="demo-controls">
35
37
  <label><input v-model="heatmapEnabled" type="checkbox" /> 启用热力图</label>
38
+ <label><input v-model="visualMapEnabled" type="checkbox" :disabled="!heatmapEnabled" /> 显示图例(visualMap)</label>
39
+ <label class="demo-slider">
40
+ 图例形态
41
+ <select v-model="visualMapType" :disabled="!heatmapEnabled || !visualMapEnabled">
42
+ <option value="ruler">连续尺 ruler</option>
43
+ <option value="piecewise">分段色块 piecewise</option>
44
+ </select>
45
+ </label>
46
+ <label><input v-model="visualMapInteractive" type="checkbox" :disabled="!heatmapEnabled || !visualMapEnabled" /> 图例可交互(点选 / 拖动区间)</label>
47
+ <label><input v-model="visualMapCustom" type="checkbox" :disabled="!heatmapEnabled || !visualMapEnabled" /> 完全自定义渲染</label>
48
+ <label class="demo-slider">
49
+ 落选值
50
+ <select v-model="visualMapOutOfRange" :disabled="!heatmapEnabled || !visualMapEnabled">
51
+ <option v-for="item in VISUAL_MAP_OUT_OF_RANGE_MODES" :key="item.value" :value="item.value">{{ item.label }}</option>
52
+ </select>
53
+ </label>
54
+ <span v-if="heatmapEnabled && visualMapEnabled" class="demo-control-hint">
55
+ {{ visualMapReadout || (visualMapCustom ? '自定义图例:点色块按钮调用 context.setSelection / setRange;不写 target 时节点、独立线路与通道一起按 max_loading_rate 门控' : '点分段或拖动区间:不写 target 时三类一起门控;落选值默认隐藏对应网架,也可切成只退热力或仅 onChange') }}<template v-if="visualMapLastChange"> · {{ visualMapLastChange }}</template>
56
+ </span>
36
57
  <label class="demo-slider">
37
58
  作用对象
38
59
  <select v-model="heatmapTarget" :disabled="!heatmapEnabled">