gis-view-webgl2 0.1.4 → 0.1.5

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/README.md +7 -7
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.d.ts +140 -20
  4. package/dist/index.js +1 -1
  5. package/docs/AI/345/257/271/350/257/235/346/261/207/346/200/273.md +45 -0
  6. package/docs/GisView.md +53 -53
  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 +36 -0
  8. package/docs/demos/ConnectDemo.vue +114 -3
  9. package/docs/demos/MinimapDemo.vue +62 -16
  10. package/docs/demos/api-index.js +15 -14
  11. package/docs/demos/gis-view-demo/GisViewDemoStage.vue +25 -16
  12. package/docs/demos/gis-view-demo/useGisViewDemo.js +27 -16
  13. package/docs/index.html +3 -3
  14. package/docs/internals/13-/351/271/260/347/234/274/345/233/276.md +6 -5
  15. package/docs/internals/16-01-/344/274/230/345/214/226/344/270/216/345/217/226/350/210/215-/344/270/212.md +5 -3
  16. package/docs/internals/18-/346/200/247/350/203/275/345/256/236/346/265/213/344/270/216WebGPU/350/257/204/344/274/260.md +12 -0
  17. package/docs/manual/03-/351/205/215/347/275/256/351/241/271.md +11 -3
  18. package/docs/manual/09-/351/200/232/351/201/223/344/270/216/345/244/232/345/233/236/347/272/277.md +1 -1
  19. package/docs/manual/10-/351/200/232/351/201/223/347/274/226/350/276/221/344/270/216/346/226/260/345/242/236.md +423 -3
  20. package/docs/manual/14-/350/247/206/345/233/276/344/270/216/347/255/233/351/200/211.md +79 -28
  21. package/docs/manual/16-/345/256/236/344/276/213/346/226/271/346/263/225/346/200/273/350/241/250.md +6 -5
  22. package/docs/manual/17-/345/217/202/346/225/260/351/200/237/346/237/245.md +5 -4
  23. package/docs/manual/18-/351/200/220/346/226/271/346/263/225/347/244/272/344/276/213.md +117 -5
  24. package/docs/manual/21-/350/257/264/346/230/216/344/270/216/345/270/270/350/247/201/351/227/256/351/242/230.md +5 -2
  25. package/docs/steps/README.md +5 -5
  26. package/docs/steps/selftest-demos.html +149 -5
  27. package/docs/steps/selftest-docs.html +3 -3
  28. package/docs/steps/selftest-full.html +315 -12
  29. package/docs/steps/selftest-perf.html +39 -1
  30. package/package.json +1 -1
@@ -364,3 +364,48 @@
364
364
  - **交互与方法性能**:定向补丁只在改动可能影响筛选结果时重跑筛选;只改展示字段时沿用原结果,`id` / 坐标 / `from` / `to` / `visible` 与函数 / 自定义运算符条件保持保守重跑。引擎新增定向的通道 / 分组范围测量,`focusOn` 不再为一段范围复制整页通道几何;事件总线在只有一条订阅时直接调用,省掉每次事件分发的快照数组。本轮没有做可信的性能基准,不提供加速倍数。
365
365
  - **核心文件**:`src/gis-view/create.js`、`engine.js`、`events.js`、`types.d.ts`、`docs/api/index.html`、`docs/demos/ExtensionDemo.vue`、`docs/demos/SearchFilterDemo.vue`、`docs/demos/ApiCoverageDemo.vue`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`docs/demos/gis-view-demo/panels/OpsPanels.vue`、`docs/demos/gis-view-demo/GisViewDemoCardHeader.vue`、`docs/demos/demos.js`、`docs/demos/api-index.js`(生成物)、`README.md`、`src/gis-view/README.md`、`docs/GisView.md`、`docs/index.html`、`docs/manual/08` / `14` / `15` / `16` / `17` / `18` / `19`、`docs/steps/README.md`、`docs/steps/selftest-features.html` / `selftest-demos.html` / `selftest-docs.html` 与本轮 aimd。
366
366
  - **验证**:`selftest-features.html` **672** 条、`selftest-demos.html` **337** 条、`selftest-docs.html` **134** 条,三页共 **1143** 条通过 / 0 失败;`node --check src/gis-view/create.js`、`npx tsc --noEmit`、`npm run build`、`node docs/steps/gen-api-index.mjs`、`npm run check:docs`(**256** 个实例成员 = **253** 个方法 + 3 个属性 / **96** 个 options / **16** 个分组 / **250** 个数据字段)与 `git diff --check` 全部通过。复查入口见 [06 的增量记录](ai/06-会话索引与复查方法.md#2026-10-23-增量修改txt四项focuson-缺省居中--文档互跳--扩展命令--性能优化)。
367
+
368
+ ## 2026-10-23 增量(「问题.txt」五项:鹰眼图回线居中 / 动态位置 / backgroundStyle / 主图样式 / 外部挂载)
369
+
370
+ 本轮仍是现有会话的继续增量,没有新建会话归档,因此不改上表的 39 条会话统计。需求原话来自仓库根目录的 `问题.txt`:① 取消通道回线后双回线只显示上面一根,应在两根中间显示;② 支持动态移动整个鹰眼图;③ 检查 `backgroundStyle` 是否生效;④ 沿用主图规则后节点尺寸与图标要和主图一致;⑤ 支持把鹰眼图单独挂到外部 `div`。
371
+
372
+ - **回线居中代表线**:`channelCircuits: false` 不再按偏移挑最靠中间的成员线;`collectMinimapData()` 取该通道分组当前可见的回线,顶点数一致时逐顶点取平均再画一根。双回线落在两线正中,三回线落在中间线,只剩一根时仍画它自己;路径结构不一致时保守回退第一条可见成员。
373
+ - **动态位置**:新增 `minimap.offset: [x, y]`,相对 `position` 指定的角移动整张鹰眼图,`x` 正数向右、`y` 正数向下,四个角语义统一;`updateOptions({ minimap: { ...old, offset } })` 即时生效,配合新增的 `getMinimapElement()` 可绑定自定义整图拖动。
374
+ - **backgroundStyle**:显式设置 `backgroundStyle` 时由容器接管底色,画布不再铺主图的不透明底色,只画继承 / 独立的图片与 GeoJSON;不写时保持原行为,想要完全透出宿主可写 `transparent`。
375
+ - **沿用主图样式**:`inheritRules` 开启时,节点半径取自引擎最终 `getPointStyle()` 尺寸(圆形按 `CIRCLE_AREA_FACTOR` 还原实际直径),并沿用主图的符号、层级与图标填充 / 描边色。圆、方、图片、SVG 与自定义图元都能显示;异步解码完成的符号会在后续帧补画。
376
+ - **外部挂载**:新增 `minimap.container`,接受元素或 CSS 选择器,把同一根鹰眼图节点移至外部宿主,`position` / `margin` / `offset` 相对该宿主计算;选择器找不到时回落主视图根节点。运行时切换容器只移动节点、不重建画布,`destroy()` 会清理挂载。
377
+ - **核心文件**:`src/gis-view/minimap.js`、`src/gis-view/create.js`、`src/gis-view/engine.js`、`src/gis-view/types.d.ts`、`docs/steps/selftest-full.html`、`docs/internals/13-鹰眼图.md`、`docs/manual/03` / `09` / `14` / `16` / `17` / `18` / `21`、`README.md`、`src/gis-view/README.md`、`docs/GisView.md`、`docs/index.html`、`docs/steps/README.md`、`docs/steps/selftest-docs.html` / `selftest-demos.html`、`docs/demos/api-index.js`(生成物)与本轮 aimd。
378
+ - **验证**:`selftest-full.html` **85** 条、`selftest-docs.html` **134** 条、`selftest-demos.html` **337** 条,三页共 **556** 条通过 / 0 失败。新增 5 条鹰眼图断言覆盖居中代表线、显式底色让画布透明、主图尺寸与 SVG 图标、外部容器挂载、`offset` 动态位移及换容器复用节点。`npx tsc --noEmit`、`node --check`(minimap / create / engine)、`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(**257** 个实例成员 = **254** 个方法 + 3 个属性 / **96** 个 options / **250** 个数据字段 / **16** 个分组)、`npm run build` 与 `git diff --check` 全部通过。复查入口见 [06 的增量记录](ai/06-会话索引与复查方法.md#2026-10-23-增量问题txt五项鹰眼图回线居中--动态位置--backgroundstyle--主图样式--外部挂载)。
379
+
380
+ ## 2026-10-23 增量:鹰眼图缩放联动与新增通道示例节点
381
+
382
+ 本轮仍是现有会话的继续增量,没有新建会话归档,因此不改上表的 39 条会话统计。需求原话来自仓库根目录的 `修改.txt` 五项与 `问题.txt` 三项:`修改.txt` ①沿用主图规则后节点要按鹰眼图与主图的比例缩小;②`dragAction: 'box'` 不依赖缩放开关;③新增跟随主图缩放的模式且与手动缩放互斥;④demo 展示指定起点新增,并让 `commitAddChannel` 可直接接收本次新增的通道 / 线路对象;⑤草稿示例点严格落在节点中心、可显隐 / 配样式,示例线路可压到真实节点下面。`问题.txt` ①`auto` 范围随相机收窄改为默认关闭的开关;②补鹰眼图拖拽 demo;③继承节点按主图与小图的视口尺寸比例缩放,不按主图放大倍数缩放。
383
+
384
+ - **鹰眼节点尺寸与范围**:`collectMinimapData()` 给继承主图尺寸的节点打 `inheritSize`;`inheritedSizeFactor()` 取小图与主图 `getViewport()` 的 CSS 宽、高较小比例,只随两边视口尺寸变化,不随主图 `/` 小图相机倍数漂移。`extentFollowCamera` 默认 `false`,`extent: 'auto'` 固定用「可见数据 ∪ 底图」;只有显式打开后才允许相机落入其中一份时按正在看的那一份收窄。
385
+ - **缩放三态与拖拽**:`zoomable` 统一为 `false` / `true` / `'follow'` 三态互斥:手动缩放、跟随主图、关闭;`followZoomScale` 是主图相对基准倍数的指数(`0` 不跟随、`1` 同倍率),`zoom` 在跟随模式作为基准倍数,`setMinimapZoom` / `zoomMinimapBy` 不抢主图控制权。`dragAction: 'box'` 在缩放关闭时也能直接框选,只有手动缩放才用 Ctrl / ⌘ 切换平移与框选;Demo 提供框选 / 平移两种整图拖拽演示。
386
+ - **新增通道对象入参**:`commitAddChannel` 兼容旧 `resolution`,也可直接传 `GisViewChannel` / `GisViewLine`,或 `{ channel, line, lines, resolution, ... }` 包装对象。对象中的端点、id、名称、路径、分组、样式与业务字段优先,缺省字段继续沿用草稿;直接线路对象除 `COMMIT_LINE_KEYS` 外的颜色 / 线宽 / 线型 / 业务字段都汇入 `lineProps`,直接通道对象支持 `lineIds` / `groups` / `lineProps` / `channelProps`,不会被容器写法误判。
387
+ - **草稿示例点与层级**:`channelDraftStyle.dots` 支持 `false` / `true` / 样式对象,统一设置 `show` / `size` / `color` / `shape`,`from` / `to` 可分别覆盖颜色、尺寸、圆点或方点;示例点固定画在真正点中的节点中心,不受多回线偏移影响。`layer: 'below-points'` 把示例线、箭头与 `customDraw` 画在真实节点之前(端点示例点仍最后画),默认 `above` 保持原层级;草稿 buffer / VAO 一并补上销毁。
388
+ - **Demo 与文档**:`ConnectDemo` 增加指定起点、示例点显隐 / 尺寸 / 形状 / 分端颜色、示例线层级和线路 / 通道对象直传;`MinimapDemo` 增加关闭 / 手动 / 跟随三态、跟随指数、范围开关、框选 / 平移拖拽演示,旧的 `minimapZoomable` 写法统一换成三态配置。同步根 `README.md`、`docs/manual/03` / `10` / `14` / `16` / `17` / `18` / `21`、`docs/internals/13-鹰眼图.md`、`docs/steps/README.md` 与 `docs/demos/api-index.js`(生成物)。
389
+ - **核心文件**:`src/gis-view/minimap.js`、`src/gis-view/create.js`、`src/gis-view/engine.js`、`src/gis-view/types.d.ts`、`docs/demos/ConnectDemo.vue`、`MinimapDemo.vue`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`GisViewDemoStage.vue`、`docs/steps/selftest-full.html`、`selftest-demos.html`、上述手册 / 内部文档与本轮 aimd。
390
+ - **验证**:`selftest-full.html` **86** 条、`selftest-features.html` **672** 条、`selftest-demos.html` **349** 条、`selftest-docs.html` **134** 条,四页共 **1241** 条通过 / 0 失败;新增断言覆盖继承节点不随主图放大、视口尺寸变化重铺、范围开关默认关闭与显式开启、三态跟随、关闭缩放时框选、对象直传与草稿示例点。`npx tsc --noEmit`、`node --check`(minimap / create / engine)、`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(**257** 个实例成员 = **254** 个方法 + 3 个属性 / **96** 个 options / **250** 个数据字段 / **43** 个事件 / **17** 个功能开关)、`npm run build` 与 `git diff --check` 全部通过。复查入口见 [06 的增量记录](ai/06-会话索引与复查方法.md#2026-10-23-增量鹰眼图缩放联动与新增通道示例节点)。
391
+
392
+ ## 2026-10-23 增量:鹰眼图继承要素尺寸与地图缩放解耦
393
+
394
+ 本轮仍是现有会话的继续增量,没有新建会话归档,因此不改上表的 39 条会话统计。需求原话来自仓库根目录的 `问题.txt` 三项:① 鹰眼图的范围跟随相机改为默认关闭;② 补鹰眼图拖拽 demo;③ 澄清「节点随主视图缩放」只指沿用主图规则时的节点 / 线路尺寸。复核确认 ① / ② 已在当前工作树实现,本轮补齐 ③:继承节点 / 线路按「小图视口 ÷ 主图视口」的较小比例缩放,独立于主图相机倍数和鹰眼图自身倍数;主图放大不改变它们,鹰眼图自身放大时才由 `pointZoomScale` / `lineZoomScale` 联动。
395
+
396
+ - **继承线宽**:`line.js` 的 `resolveLineStyleInto()` 记录样式链原始宽度 `baseWidth`(不含热力倍数 / 整体倍数 / 缩放联动),`engine.js` 新增内部 `getLineStyle(index)` 快照;`create.js` 在沿用主图线路时写入 `entry.width` 并标记 `inheritWidth`,与节点的 `inheritSize` 走同一份视口比例。
397
+ - **缩放拆层**:`minimap.js` 对继承节点使用 `pointSizeScale × pointZoomScale × inheritedSizeFactor()`,对继承线路使用 `lineWidthScale × lineZoomScale × inheritedSizeFactor()`;`pointMapZoomScale` / `lineMapZoomScale` 只作用于小图自有规则 / 样式。点 / 线路缓存键同步包含各自系数,没有继承线路时继承系数固定为 1。
398
+ - **Demo 与文档**:`MinimapDemo` 默认切到沿用主图,拆分节点 / 线路整体倍数与小图缩放指数控件,并保留框选 / 平移拖拽演示;主 demo 在沿用模式下禁用「节点跟主图 / 线路跟主图」并更新提示。同步 `types.d.ts` 注释、根 `README.md`、`src/gis-view/README.md`、`docs/manual/03` / `14`、`docs/internals/13-鹰眼图.md`,重新生成 `docs/demos/api-index.js`。
399
+ - **核心文件**:`src/gis-view/line.js`、`src/gis-view/engine.js`、`src/gis-view/create.js`、`src/gis-view/minimap.js`、`src/gis-view/types.d.ts`、`docs/demos/MinimapDemo.vue`、`docs/demos/gis-view-demo/GisViewDemoStage.vue`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`docs/steps/selftest-full.html`、`docs/steps/selftest-demos.html` 与本轮文档。
400
+ - **验证**:`selftest-full.html` **92** 条、`selftest-features.html` **672** 条、`selftest-demos.html` **351** 条、`selftest-docs.html` **134** 条,四页共 **1249** 条通过 / 0 失败;新增 8 条断言覆盖继承线路 / 节点在主图放大时尺寸不变、`pointSizeScale` / `lineWidthScale` 对继承要素生效、小图自身放大按 `pointZoomScale` / `lineZoomScale` 联动,以及 demo 两个独立整体倍数控件。`npx tsc --noEmit`、`node --check`(minimap / create / engine / line)、`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(**257** 个实例成员 = **254** 个方法 + 3 个属性 / **96** 个 options / **250** 个数据字段 / **43** 个事件 / **17** 个功能开关)、`npm run build` 与 `git diff --check` 全部通过。复查入口见 [06 的增量记录](ai/06-会话索引与复查方法.md#2026-10-23-增量鹰眼图继承要素尺寸与地图缩放解耦)。
401
+
402
+ ## 2026-10-23 增量(「修改.txt」三项:commitAddChannel 文档 / 传参示例 / 线路半跳过)
403
+
404
+ 本轮仍是现有会话的继续增量,没有新建会话归档,因此不改上表的 39 条会话统计。需求原话来自仓库根目录的 `修改.txt` 三项:① 说明 `commitAddChannel` 有哪些传参、支持哪些写法;② 把方法用法、传参和示例写详细;③ 继续优化组件性能。
405
+
406
+ - **`commitAddChannel` 入参口径**:手册 `10` 的「对象直传」扩写为五种写法:无参、旧 resolution、直接线路对象、直接通道对象(必须有 `lineIds`)、容器(`channel` / `line` / `lines` / `lineData` / `lineItems` / `channelGroups` / `group` / `channelProps` / `lineProps` / `resolution`)。明确草稿只支持 `from`、没有 `to`;`line` 缺省是独立线路,`lines` 才是成员回线表;空数组沿用草稿;直接通道的 `id` 只是通道 id,回线 id 来自 `lineIds`;直接通道自己的 `lineProps` 生效,容器里的 `channel.lineProps` 不合并;分组优先级 `channelGroups > group > channel.groups`;并进已有通道 / 分组要用容器并显式写 `resolution`。
407
+ - **示例与错误说明**:`ready` 里的方案读数不能整条回传,统一只取 `{ type, groupId, groupIndex, channelId }` 子集;删除“整条 option 可直接提交”的旧示例。`groups[].lineIds` 写了本次未生成的 id 改为 warning + 按成员表调和,不再列为失败原因;返回结果的 `channelIndex` 改为“成功时为通道下标、独立线路为 -1,失败通常不返回,事件载荷按 -1 兜底”。同步扩写 `18` 的逐方法示例(五种写法、只给 `channel.lineIds`、容器逐条字段、空数组、端点 / 路由覆盖、并组、连续提交、结果读取),并细化 `16` / `17` 与 `types.d.ts` 的 JSDoc。
408
+ - **线路半跳过**:`engine.js` 在节点半跳过成立后,再核对线路数组与通道声明逐元素同引用、隐藏集合 / 通道车道输入 / 线路与状态样式快照未变,且没有追加补点补线;命中时跳过 `resolveLines`、线路索引、虚线槽位、层序与线路包围盒重算,直接复用上一轮线路半包围盒。追加补线与拖点 / 拐点 / 通道骨架等增量改线会把新路径并进缓存;没有可信读数时记 `lineHalfOutOfSync`,下一轮放弃跳过。`selftest-perf.html` 新增 3 条断言:同一批点线连交 5 次条数与线路实例数不变、通道声明未变时回线派生折线原样保留、换通道骨架时线路几何必须重推。
409
+ - **实测**:20000 点 / 8000 线同一批对象回灌 5 次取中位,**14.3 ms → 6.3 ms**(优化后 5.6 / 6.3 / 6.3 / 6.4 / 10.7 ms)。
410
+ - **核心文件**:`src/gis-view/engine.js`、`src/gis-view/types.d.ts`、`docs/manual/10` / `16` / `17` / `18`、`docs/steps/selftest-perf.html`、`docs/internals/16-01-优化与取舍-上.md`、`docs/internals/18-性能实测与WebGPU评估.md`、`docs/demos/api-index.js`(生成物)、本轮 aimd。
411
+ - **验证**:`node --check`(engine / create)、`node docs/steps/gen-api-index.mjs`、`npm run check:docs`(**257** 个实例成员 = **254** 个方法 + 3 个属性 / **96** 个 options / **250** 个数据字段 / **43** 个事件 / **17** 个功能开关)、五页自测 `full 92` + `features 672` + `demos 351` + `docs 134` + `perf 167` = **1416** 条通过 / 0 失败、`npx tsc --noEmit`、`npm run build` 与 `git diff --check` 全部通过。复查入口见 [06 的增量记录](ai/06-会话索引与复查方法.md#2026-10-23-增量修改txt三项commitaddchannel-文档--传参示例--线路半跳过)。
package/docs/GisView.md CHANGED
@@ -1,53 +1,53 @@
1
- # GisView
2
-
3
- `GisView` 是一套不依赖任何第三方图形库的 WebGL2 矢量视图:渲染层是原生 WebGL2(GLSL ES 3.00 + 实例化绘制),交互层只有指针与滚轮,界面只内置可选的小地图(配 `minimap` 才有,见「鹰眼图」),其余全靠使用方。它没有 Vue 组件形态,用 `createGisView(dom, options)` 把画布直接挂到传入的 DOM 上,宽高默认跟随容器。
4
-
5
- 控制面板、读数面板、图例这类视图工具都不内置:组件只提供画布与实例方法,样式和布局完全由使用方决定,后续改样式不需要等待组件升级。数据侧该有的都给了:按属性筛选(默认只隐藏,也可显式从数据删除;点被过滤时绑定线路与通道一起消失,大数据量走 Web Worker)、按属性批量配色换符号、节点标签与点 / 线 / 通道的悬浮提示,都可以通过 options 或实例方法配置。
6
-
7
- **这份手册按主题拆成了 21 章,正文在 [`docs/manual/`](manual/) 下**:找方法先看 [16 实例方法总表](manual/16-实例方法总表.md),查参数跳 [17 参数速查](manual/17-参数速查.md),要能直接复制的调用看 [18 逐方法示例](manual/18-逐方法示例.md);只想先跑起来看 [01 快速开始](manual/01-快速开始.md)。
8
-
9
- - 想在页面上按方法名搜、直接看示例:打开 [API 速查(方法 + 示例)](api/index.html)(清单就是从 17 / 18 两章生成的;支持深浅主题、左侧分组跟随与 `#成员名` 深链);要边改边跑用 [调试演示页](playground/index.html)。
10
- - 「某个特性怎么实现、为什么这么做」看 [GisView 实现原理](GisView实现原理.md);数据的标准写法与五套口径看 [数据格式](数据格式.md)。
11
- - 复制 / 合并 / 通道分组 / 拐点要接真实后端:请求头、body、成功响应、409 / 500、幂等与前端重试流程看 [编辑接口协议](接口协议.md);成功响应怎么落到本地数据(`idMap` 改写、合并对账、分组 / 拐点覆盖、409 局部恢复)见其中的「前端落地映射」。
12
- - 后端 DTO 与内置列名不一致时,不必改组件:用 `defineExportFormat`(或底层的 `registerExportFormat`)注册一个同步导出格式,把标准文档映射成自己的表结构,见 [自定义导出格式](manual/15-导出与集成.md#自定义导出格式后端-dto)。
13
- - 想照着源码从零写一遍看 [从 0 到完整的实现](从0到完整的实现.md);逐文件的教程与自测页在 [docs/steps](steps/README.md)(页面:[docs/steps/index.html](steps/index.html))。
14
-
15
- ## 手册目录
16
-
17
- | 章 | 讲什么 |
18
- | --- | --- |
19
- | [01 快速开始](manual/01-快速开始.md) | 引入与最小示例:装什么、怎么把画布挂到 DOM 上 |
20
- | [02 坐标与数据](manual/02-坐标与数据.md) | 世界坐标 / 经纬度映射、相机与像素、数据字段全表 |
21
- | [03 配置项(options)](manual/03-配置项.md) | 全部 options 的总表与逐个详解(默认值、落点、相关开关) |
22
- | [04 事件与回调](manual/04-事件与回调.md) | 回调清单、事件订阅、两层功能开关、配置提醒 |
23
- | [05 画质与批量更新](manual/05-画质与批量更新.md) | quality 四档与自动升降;batch 把一批改动作一次提交 |
24
- | [06 数据与场景更新](manual/06-数据与场景更新.md) | 整份换数据 / 增量追加 / 加载完成回调 / 按方法新增要素 / 历史 |
25
- | [07 指针与要素编辑](manual/07-指针与要素编辑.md) | 点击与样式、指针事件全字段、光标、拖拽点、复制 / 合并 / 删除 |
26
- | [08 选中与拐点](manual/08-选中与拐点.md) | 选中与拖动的层级、框选、接口选中、线路拐点的增删改 |
27
- | [09 通道与多回线](manual/09-通道与多回线.md) | 通道的数据结构、createChannels 批量生成、分组与选中模式 |
28
- | [10 通道编辑与新增](manual/10-通道编辑与新增.md) | 分组拐点的增删、右键交互框、新增通道的草稿流程、改名与增删回线 |
29
- | [11 样式与规则](manual/11-样式与规则.md) | 点配置、线配置、条件语言(筛选 / 规则 / 标签共用)与批量样式规则 |
30
- | [12 标签与装饰](manual/12-标签与装饰.md) | 节点 / 线路标签、标签拖动与编辑、节点与线路装饰、动态装饰器草稿、悬浮提示 |
31
- | [13 动效与图元](manual/13-动效与图元.md) | 热力图、动画效果、线路方向箭头、贴图预热与自定义图元 |
32
- | [14 视图与筛选](manual/14-视图与筛选.md) | 筛选、搜索定位、初始视图与缩放范围、背景层、鹰眼图、近义入口 |
33
- | [15 导出与集成](manual/15-导出与集成.md) | 导出图片 / 选中节点 / 数据、自定义导出格式,插件、自建界面与键盘交互 |
34
- | [16 实例方法总表](manual/16-实例方法总表.md) | 按功能分组的实例方法主表(找方法从这一章开始) |
35
- | [17 参数速查(逐个方法)](manual/17-参数速查.md) | 256 个成员逐个列全:参数、默认值与返回 |
36
- | [18 逐方法示例(复制就能跑)](manual/18-逐方法示例.md) | 每个成员一段可复制的调用示例(API 速查页读的就是这一章) |
37
- | [19 读数与拖拽预览](manual/19-读数与拖拽预览.md) | 自建界面常用的读数 / 定位方法;拖拽落点预览 |
38
- | [20 性能与大数据](manual/20-性能与大数据.md) | 十万级数据的开关与实测、WebGPU 取舍、渲染后端开关 |
39
- | [21 说明与常见问题](manual/21-说明与常见问题.md) | 边界与口径、FAQ、类型定义索引 |
40
-
41
- ## 快速跳转(按任务)
42
-
43
- - **上手**:[引入](manual/01-快速开始.md#引入) · [基础用法](manual/01-快速开始.md#基础用法) · [坐标与数据](manual/02-坐标与数据.md)
44
- - **配置与回调**:[options 总表](manual/03-配置项.md#options) · [回调](manual/04-事件与回调.md#回调) · [功能开关](manual/04-事件与回调.md#功能开关)
45
- - **通道**:[通道与多回线](manual/09-通道与多回线.md) · [通道编辑与新增](manual/10-通道编辑与新增.md) · [分组拐点](manual/10-通道编辑与新增.md#分组拐点把某一组拉走)
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#自定义图元)
48
- - **视图**:[筛选](manual/14-视图与筛选.md#筛选) · [搜索与定位](manual/14-视图与筛选.md#搜索与定位) · [适应视图的节点间距](manual/14-视图与筛选.md#适应视图的节点间距fitspacing) · [背景层](manual/14-视图与筛选.md#背景层) · [鹰眼图](manual/14-视图与筛选.md#鹰眼图)
49
- - **导出与集成**:[导出数据](manual/15-导出与集成.md#导出数据) · [自定义导出格式](manual/15-导出与集成.md#自定义导出格式后端-dto) · [插件](manual/15-导出与集成.md#插件) · [实例命令](manual/15-导出与集成.md#实例命令) · [六类扩展点怎么选](manual/15-导出与集成.md#六类扩展点怎么选) · [自建界面](manual/15-导出与集成.md#自建界面)
50
- - **查方法**:[实例方法总表](manual/16-实例方法总表.md) · [参数速查](manual/17-参数速查.md) · [逐方法示例](manual/18-逐方法示例.md) · [读数与拖拽预览](manual/19-读数与拖拽预览.md)
51
- - **概念与排查**:[大数据展示模式(denseMode)](manual/20-性能与大数据.md#大数据展示模式densemode) · [大数据量](manual/20-性能与大数据.md#大数据量) · [常见问题](manual/21-说明与常见问题.md#常见问题) · [类型定义索引](manual/21-说明与常见问题.md#类型定义索引)
52
-
53
- > 本页也可以从文档中心(`docs/index.html`)打开:左侧清单里 `GisView.md` 是这一页,下面紧跟着 21 章手册。
1
+ # GisView
2
+
3
+ `GisView` 是一套不依赖任何第三方图形库的 WebGL2 矢量视图:渲染层是原生 WebGL2(GLSL ES 3.00 + 实例化绘制),交互层只有指针与滚轮,界面只内置可选的小地图(配 `minimap` 才有,见「鹰眼图」),其余全靠使用方。它没有 Vue 组件形态,用 `createGisView(dom, options)` 把画布直接挂到传入的 DOM 上,宽高默认跟随容器。
4
+
5
+ 控制面板、读数面板、图例这类视图工具都不内置:组件只提供画布与实例方法,样式和布局完全由使用方决定,后续改样式不需要等待组件升级。数据侧该有的都给了:按属性筛选(默认只隐藏,也可显式从数据删除;点被过滤时绑定线路与通道一起消失,大数据量走 Web Worker)、按属性批量配色换符号、节点标签与点 / 线 / 通道的悬浮提示,都可以通过 options 或实例方法配置。
6
+
7
+ **这份手册按主题拆成了 21 章,正文在 [`docs/manual/`](manual/) 下**:找方法先看 [16 实例方法总表](manual/16-实例方法总表.md),查参数跳 [17 参数速查](manual/17-参数速查.md),要能直接复制的调用看 [18 逐方法示例](manual/18-逐方法示例.md);只想先跑起来看 [01 快速开始](manual/01-快速开始.md)。
8
+
9
+ - 想在页面上按方法名搜、直接看示例:打开 [API 速查(方法 + 示例)](api/index.html)(清单就是从 17 / 18 两章生成的;支持深浅主题、左侧分组跟随与 `#成员名` 深链);要边改边跑用 [调试演示页](playground/index.html)。
10
+ - 「某个特性怎么实现、为什么这么做」看 [GisView 实现原理](GisView实现原理.md);数据的标准写法与五套口径看 [数据格式](数据格式.md)。
11
+ - 复制 / 合并 / 通道分组 / 拐点要接真实后端:请求头、body、成功响应、409 / 500、幂等与前端重试流程看 [编辑接口协议](接口协议.md);成功响应怎么落到本地数据(`idMap` 改写、合并对账、分组 / 拐点覆盖、409 局部恢复)见其中的「前端落地映射」。
12
+ - 后端 DTO 与内置列名不一致时,不必改组件:用 `defineExportFormat`(或底层的 `registerExportFormat`)注册一个同步导出格式,把标准文档映射成自己的表结构,见 [自定义导出格式](manual/15-导出与集成.md#自定义导出格式后端-dto)。
13
+ - 想照着源码从零写一遍看 [从 0 到完整的实现](从0到完整的实现.md);逐文件的教程与自测页在 [docs/steps](steps/README.md)(页面:[docs/steps/index.html](steps/index.html))。
14
+
15
+ ## 手册目录
16
+
17
+ | 章 | 讲什么 |
18
+ | --- | --- |
19
+ | [01 快速开始](manual/01-快速开始.md) | 引入与最小示例:装什么、怎么把画布挂到 DOM 上 |
20
+ | [02 坐标与数据](manual/02-坐标与数据.md) | 世界坐标 / 经纬度映射、相机与像素、数据字段全表 |
21
+ | [03 配置项(options)](manual/03-配置项.md) | 全部 options 的总表与逐个详解(默认值、落点、相关开关) |
22
+ | [04 事件与回调](manual/04-事件与回调.md) | 回调清单、事件订阅、两层功能开关、配置提醒 |
23
+ | [05 画质与批量更新](manual/05-画质与批量更新.md) | quality 四档与自动升降;batch 把一批改动作一次提交 |
24
+ | [06 数据与场景更新](manual/06-数据与场景更新.md) | 整份换数据 / 增量追加 / 加载完成回调 / 按方法新增要素 / 历史 |
25
+ | [07 指针与要素编辑](manual/07-指针与要素编辑.md) | 点击与样式、指针事件全字段、光标、拖拽点、复制 / 合并 / 删除 |
26
+ | [08 选中与拐点](manual/08-选中与拐点.md) | 选中与拖动的层级、框选、接口选中、线路拐点的增删改 |
27
+ | [09 通道与多回线](manual/09-通道与多回线.md) | 通道的数据结构、createChannels 批量生成、分组与选中模式 |
28
+ | [10 通道编辑与新增](manual/10-通道编辑与新增.md) | 分组拐点的增删、右键交互框、新增通道的草稿流程、改名与增删回线 |
29
+ | [11 样式与规则](manual/11-样式与规则.md) | 点配置、线配置、条件语言(筛选 / 规则 / 标签共用)与批量样式规则 |
30
+ | [12 标签与装饰](manual/12-标签与装饰.md) | 节点 / 线路标签、标签拖动与编辑、节点与线路装饰、动态装饰器草稿、悬浮提示 |
31
+ | [13 动效与图元](manual/13-动效与图元.md) | 热力图、动画效果、线路方向箭头、贴图预热与自定义图元 |
32
+ | [14 视图与筛选](manual/14-视图与筛选.md) | 筛选、搜索定位、初始视图与缩放范围、背景层、鹰眼图、近义入口 |
33
+ | [15 导出与集成](manual/15-导出与集成.md) | 导出图片 / 选中节点 / 数据、自定义导出格式,插件、自建界面与键盘交互 |
34
+ | [16 实例方法总表](manual/16-实例方法总表.md) | 按功能分组的实例方法主表(找方法从这一章开始) |
35
+ | [17 参数速查(逐个方法)](manual/17-参数速查.md) | 257 个成员逐个列全:参数、默认值与返回 |
36
+ | [18 逐方法示例(复制就能跑)](manual/18-逐方法示例.md) | 每个成员一段可复制的调用示例(API 速查页读的就是这一章) |
37
+ | [19 读数与拖拽预览](manual/19-读数与拖拽预览.md) | 自建界面常用的读数 / 定位方法;拖拽落点预览 |
38
+ | [20 性能与大数据](manual/20-性能与大数据.md) | 十万级数据的开关与实测、WebGPU 取舍、渲染后端开关 |
39
+ | [21 说明与常见问题](manual/21-说明与常见问题.md) | 边界与口径、FAQ、类型定义索引 |
40
+
41
+ ## 快速跳转(按任务)
42
+
43
+ - **上手**:[引入](manual/01-快速开始.md#引入) · [基础用法](manual/01-快速开始.md#基础用法) · [坐标与数据](manual/02-坐标与数据.md)
44
+ - **配置与回调**:[options 总表](manual/03-配置项.md#options) · [回调](manual/04-事件与回调.md#回调) · [功能开关](manual/04-事件与回调.md#功能开关)
45
+ - **通道**:[通道与多回线](manual/09-通道与多回线.md) · [通道编辑与新增](manual/10-通道编辑与新增.md) · [分组拐点](manual/10-通道编辑与新增.md#分组拐点把某一组拉走)
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#自定义图元)
48
+ - **视图**:[筛选](manual/14-视图与筛选.md#筛选) · [搜索与定位](manual/14-视图与筛选.md#搜索与定位) · [适应视图的节点间距](manual/14-视图与筛选.md#适应视图的节点间距fitspacing) · [背景层](manual/14-视图与筛选.md#背景层) · [鹰眼图](manual/14-视图与筛选.md#鹰眼图)
49
+ - **导出与集成**:[导出数据](manual/15-导出与集成.md#导出数据) · [自定义导出格式](manual/15-导出与集成.md#自定义导出格式后端-dto) · [插件](manual/15-导出与集成.md#插件) · [实例命令](manual/15-导出与集成.md#实例命令) · [六类扩展点怎么选](manual/15-导出与集成.md#六类扩展点怎么选) · [自建界面](manual/15-导出与集成.md#自建界面)
50
+ - **查方法**:[实例方法总表](manual/16-实例方法总表.md) · [参数速查](manual/17-参数速查.md) · [逐方法示例](manual/18-逐方法示例.md) · [读数与拖拽预览](manual/19-读数与拖拽预览.md)
51
+ - **概念与排查**:[大数据展示模式(denseMode)](manual/20-性能与大数据.md#大数据展示模式densemode) · [大数据量](manual/20-性能与大数据.md#大数据量) · [常见问题](manual/21-说明与常见问题.md#常见问题) · [类型定义索引](manual/21-说明与常见问题.md#类型定义索引)
52
+
53
+ > 本页也可以从文档中心(`docs/index.html`)打开:左侧清单里 `GisView.md` 是这一页,下面紧跟着 21 章手册。
@@ -357,6 +357,42 @@
357
357
  - **核心文件**:`src/gis-view/create.js`、`engine.js`、`events.js`、`types.d.ts`、`docs/api/index.html`、`docs/demos/ExtensionDemo.vue`、`SearchFilterDemo.vue`、`ApiCoverageDemo.vue`、`gis-view-demo/useGisViewDemo.js`、`gis-view-demo/panels/OpsPanels.vue`、`gis-view-demo/GisViewDemoCardHeader.vue`、`demos.js`、`api-index.js`(生成物)、`README.md`、`src/gis-view/README.md`、`docs/GisView.md`、`docs/index.html`、`docs/manual/08` / `14` / `15` / `16` / `17` / `18` / `19`、`docs/steps/README.md`、`docs/steps/selftest-features.html` / `selftest-demos.html` / `selftest-docs.html` 与本轮 aimd。
358
358
  - **验证**:`selftest-features.html` **672** 条、`selftest-demos.html` **337** 条、`selftest-docs.html` **134** 条,三页共 **1143** 条通过 / 0 失败;`node --check src/gis-view/create.js`、`npx tsc --noEmit`、`npm run build`、`node docs/steps/gen-api-index.mjs`、`npm run check:docs`(256 个实例成员 = 253 个方法 + 3 个属性 / 96 个 options / 16 个分组 / 250 个数据字段)与 `git diff --check` 全部通过。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-23-增量修改txt四项focuson-缺省居中--文档互跳--扩展命令--性能优化)。
359
359
 
360
+ ### 2026-10-23 增量(「问题.txt」五项:鹰眼图回线居中 / 动态位置 / backgroundStyle / 主图样式 / 外部挂载)
361
+
362
+ 本轮仍是现有会话的继续增量,没有独立会话归档,因此不改上表的 39 条统计。需求原话来自仓库根目录的 `问题.txt`:取消通道回线后双回线应居中、支持动态移动鹰眼图、确认 `backgroundStyle` 生效、沿用主图后节点尺寸与图标一致、支持挂到外部 `div`。
363
+
364
+ - **回线居中**:`create.js` 的 `averageMinimapPaths()` 在当前可见成员间逐顶点平均,`channelCircuits: false` 只画一根居中代表线;双回线位于两线中间,三回线落在中间线,成员只剩一条时原样保留,路径结构不一致时保守回退第一条可见路径。
365
+ - **动态位置与外部挂载**:`minimap.offset` 使用统一的正向右 / 正向下位移,`updateOptions` 可即时移动;`minimap.container` 支持元素或选择器,`syncAttachment()` 只移动同一根节点;新增 `getMinimapElement()` 供宿主绑定整图拖动。宿主需要定位上下文,选择器失效时回落主视图根节点。
366
+ - **backgroundStyle 与主图样式**:显式 `backgroundStyle` 时画布不再铺不透明主图底色,保留图片 / GeoJSON;`inheritRules` 的节点尺寸与符号改为取主图最终 `getPointStyle()` 结果,圆形用 `CIRCLE_AREA_FACTOR` 还原,图片 / SVG / 自定义图元支持异步加载后补画。
367
+ - **文档与验证**:同步手册 `03` / `09` / `14` / `16` / `17` / `18` / `21`、`docs/internals/13-鹰眼图.md`、根 `README.md`、`src/gis-view/README.md`、`docs/GisView.md` 与文档索引;`selftest-full.html` 增加 5 条断言。`selftest-full.html` **85** 条、`selftest-docs.html` **134** 条、`selftest-demos.html` **337** 条,三页共 **556** 条通过 / 0 失败;`npx tsc --noEmit`、`node --check`(minimap / create / engine)、`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(**257** 个实例成员 = **254** 个方法 + 3 个属性 / **96** 个 options / **250** 个数据字段 / **16** 个分组)、`npm run build` 与 `git diff --check` 全部通过。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-23-增量问题txt五项鹰眼图回线居中--动态位置--backgroundstyle--主图样式--外部挂载)。
368
+
369
+ ### 2026-10-23 增量:鹰眼图缩放联动与新增通道示例节点
370
+
371
+ 本轮仍是现有会话的继续增量,没有独立会话归档,因此不改上表的 39 条统计。需求原话来自仓库根目录的 `修改.txt` 五项与 `问题.txt` 三项:沿用主图规则后节点按鹰眼图 / 主图比例缩放、`box` 拖拽不再依赖缩放、增加与手动缩放互斥的跟随主图模式、`commitAddChannel` 直接接收新增对象、草稿示例点居中且可配、`auto` 范围跟相机改为默认关闭、补鹰眼图拖拽 demo,以及继承节点按两边视口尺寸而不是主图放大倍数缩放。
372
+
373
+ - **鹰眼图**:`minimap.js` 的 `inheritedSizeFactor()` 改用两边 CSS 视口宽高的较小比例,`inheritSize` 节点不再跟主图相机倍数变化;`extentFollowCamera` 默认 `false`,`extent: 'auto'` 默认保持「数据 ∪ 底图」;`zoomable` 三态为 `false` / `true` / `'follow'`,`followZoomScale` 控制跟随指数,手动缩放与跟随互斥,跟随档不接受 `setMinimapZoom` / `zoomMinimapBy` 抢控制;`dragAction: 'box'` 在关闭缩放时也可用。
374
+ - **新增通道**:`commitAddChannel` 增加对象入参,直接给通道 / 线路或 `{ channel, line, lines, ... }` 均可;对象字段优先、缺省续用草稿,直接线路的业务字段与样式透传到 `lineProps`,直接通道支持 `lineIds` / `groups` / `lineProps` / `channelProps`。草稿示例点固定在真实节点中心,`dots` 支持显隐 / 分端样式 / 尺寸 / 圆方形状,`channelDraftStyle.layer` 可设 `'below-points'` 让示例线压在真实节点下面。
375
+ - **Demo 与文档**:`ConnectDemo` 展示指定起点、示例点样式与对象直传;`MinimapDemo` 展示三态缩放、跟随指数、范围开关与框选 / 平移拖拽。同步 `README.md`、`docs/manual/03` / `10` / `14` / `16` / `17` / `18` / `21`、`docs/internals/13-鹰眼图.md`、`docs/steps/README.md` 和 `docs/demos/api-index.js`。
376
+ - **验证**:`selftest-full.html` **86** 条、`selftest-features.html` **672** 条、`selftest-demos.html` **349** 条、`selftest-docs.html` **134** 条,四页共 **1241** 条通过 / 0 失败;`npx tsc --noEmit`、`node --check`(minimap / create / engine)、`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(257 个实例成员 / 96 个 options / 250 个数据字段 / 43 个事件 / 17 个功能开关)、`npm run build` 与 `git diff --check` 全部通过。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-23-增量鹰眼图缩放联动与新增通道示例节点)。
377
+
378
+ ### 2026-10-23 增量:鹰眼图继承要素尺寸与地图缩放解耦
379
+
380
+ 本轮仍是现有会话的继续增量,没有独立会话归档,因此不改上表的 39 条统计。需求原话来自仓库根目录的 `问题.txt` 三项:范围跟随相机默认关闭、补鹰眼图拖拽 demo、澄清继承节点 / 线路的尺寸语义。前两项已在当前工作树实现;本轮完成第三项,把继承尺寸与主图相机倍数彻底解耦。
381
+
382
+ - **继承线宽**:`resolveLineStyleInto()` 新增 `baseWidth`,`engine.getLineStyle(index)` 返回样式链原始线宽;`collectMinimapData()` 在未配自有 `lineRules` 时写入继承线宽并标记 `inheritWidth`,与节点的 `inheritSize` 一样乘两边 CSS 视口的较小比例。
383
+ - **缩放口径**:继承节点 = `pointSizeScale × 小图自身缩放指数 × 视口比例`,继承线路 = `lineWidthScale × 小图自身缩放指数 × 视口比例`;主图缩放不进入这两条公式,`pointMapZoomScale` / `lineMapZoomScale` 只作用于小图自有规则 / 样式。点 / 线路缓存键同步拆分这些系数,避免继承尺寸与主图倍数错误互相失效。
384
+ - **Demo 与文档**:`MinimapDemo` 默认沿用主图,提供节点 / 线路各自的整体倍数与小图缩放指数控件,保留框选 / 平移拖拽演示;主 demo 在沿用模式下禁用地图倍数联动。同步类型注释、根 `README.md`、`src/gis-view/README.md`、手册 `03` / `14`、内部文档 `13` 与生成的 `docs/demos/api-index.js`。
385
+ - **验证**:`selftest-full.html` **92** 条、`selftest-features.html` **672** 条、`selftest-demos.html` **351** 条、`selftest-docs.html` **134** 条,四页共 **1249** 条通过 / 0 失败;`npx tsc --noEmit`、`node --check`(minimap / create / engine / line)、`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(257 个实例成员 / 96 个 options / 250 个数据字段 / 43 个事件 / 17 个功能开关)、`npm run build` 与 `git diff --check` 全部通过。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-23-增量鹰眼图继承要素尺寸与地图缩放解耦)。
386
+
387
+ ### 2026-10-23 增量(「修改.txt」三项:commitAddChannel 文档 / 传参示例 / 线路半跳过)
388
+
389
+ 本轮仍是现有会话的继续增量,没有独立会话归档,因此不改上表的 39 条统计。需求原话来自仓库根目录的 `修改.txt` 三项:说明 `commitAddChannel` 的传参与写法、把方法用法和示例写详细、继续优化组件性能。
390
+
391
+ - **文档**:手册 `10` 补齐五种入参(无参 / 旧 resolution / 直接线路 / 直接通道 / 容器)、精确字段优先级与并组限制;明确草稿只认 `from`(没有 `to`)、直接通道 `id` 不是回线种子、`line` 与 `lines` 语义不同、空数组沿用草稿、容器不合并 `channel.lineProps`、方案读数只能取 `{ type, groupId, groupIndex, channelId }` 子集。`18` 增加逐项示例,`16` / `17` 与 `types.d.ts` 同步参数说明。
392
+ - **性能**:`engine.js` 新增线路半跳过;命中时复用上一轮线路解析结果与包围盒,跳过 `resolveLines` 及索引 / 虚线 / 层序 / 包围盒几趟。追加补线与增量改线维护线路半包围盒,`lineHalfOutOfSync` 负责失效兜底。20000 点 / 8000 线原样回灌中位 **14.3 → 6.3 ms**。
393
+ - **自测与文档**:`selftest-perf.html` 新增 3 条断言,锁住原样回灌、通道声明未变沿用派生折线、换骨架必须重推几何;性能页 **167** 条通过。性能记录同步到内部文档 `16-01` 的 16.37 与 `18` 的第十六轮。
394
+ - **验证**:五页自测 full **92** / features **672** / demos **351** / docs **134** / perf **167**,合计 **1416** 条通过 / 0 失败;`node --check`、`node docs/steps/gen-api-index.mjs`、`npm run check:docs`(257 个实例成员 / 96 个 options / 250 个数据字段 / 43 个事件 / 17 个功能开关)、`npx tsc --noEmit`、`npm run build` 与 `git diff --check` 全部通过。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-23-增量修改txt三项commitaddchannel-文档--传参示例--线路半跳过)。
395
+
360
396
  ## 六、怎么自己复查
361
397
 
362
398
  会话文件是逐行 JSON,不用整份读 —— 只挑两种行解析就够:`session_meta` 行里的 `payload.cwd` 认项目,`payload.type === 'user_message'` 行里的 `payload.message` 是用户原话:
@@ -28,6 +28,13 @@ const arrow = ref(true)
28
28
  const arrowSize = ref(12)
29
29
  const arrowPositionsText = ref('0.5')
30
30
  const circuitSpacing = ref(12)
31
+ const startPointId = ref('')
32
+ const dotsVisible = ref(true)
33
+ const dotSize = ref(5)
34
+ const startDotColor = ref('#2f6fd0')
35
+ const endDotColor = ref('#d9544d')
36
+ const dotShape = ref('circle')
37
+ const draftLayer = ref('above')
31
38
  const draft = ref(null)
32
39
  const actionText = ref('配置好线条之后点「开始连线」,依次点两个节点')
33
40
  const dataText = ref('正在创建视图…')
@@ -72,6 +79,10 @@ const createInitialLines = () => {
72
79
  const isChannel = computed(() => linkKind.value !== 'line')
73
80
  const circuits = computed(() => linkKind.value === 'channel-3' ? 3 : linkKind.value === 'channel-2' ? 2 : 1)
74
81
  const arrowPositions = computed(() => arrowPositionsText.value.split(',').map(value => Number(value.trim())).filter(value => Number.isFinite(value)))
82
+ const startPointLabel = computed(() => {
83
+ const point = points.find(item => String(item.id) === String(startPointId.value))
84
+ return point ? point.name ?? String(point.id) : ''
85
+ })
75
86
  const isDraftLive = computed(() => Boolean(draft.value) && ['start', 'from', 'ready', 'restart', 'pick'].includes(draft.value.phase))
76
87
  const canFinish = computed(() => draft.value?.phase === 'ready')
77
88
  const draftText = computed(() => {
@@ -110,10 +121,19 @@ const currentDraftStyle = () => ({
110
121
  color: lineColor.value,
111
122
  width: lineWidth.value,
112
123
  dot: 4,
124
+ dots: dotsVisible.value
125
+ ? {
126
+ size: dotSize.value,
127
+ shape: dotShape.value,
128
+ from: { color: startDotColor.value },
129
+ to: { color: endDotColor.value }
130
+ }
131
+ : false,
113
132
  arrow: arrow.value,
114
133
  arrowSize: arrowSize.value,
115
134
  arrowPositions: arrowPositions.value,
116
- circuitSpacing: circuitSpacing.value
135
+ circuitSpacing: circuitSpacing.value,
136
+ layer: draftLayer.value
117
137
  })
118
138
 
119
139
  /** 预览与真实落地共用同一份线条字段:颜色 / 线宽 / 方向箭头都从这里出发 */
@@ -129,6 +149,7 @@ const startDraft = () => {
129
149
  }
130
150
  view.endAddChannel()
131
151
  view.beginAddChannel({
152
+ ...(startPointId.value ? { from: startPointId.value } : {}),
132
153
  kind: isChannel.value ? 'channel' : 'line',
133
154
  circuits: circuits.value,
134
155
  routing: routing.value,
@@ -136,7 +157,9 @@ const startDraft = () => {
136
157
  channelDraftStyle: currentDraftStyle(),
137
158
  lineProps: currentLineProps()
138
159
  })
139
- actionText.value = `开始连线:先点起点,再点终点(${isChannel.value ? `通道 ${circuits.value} 回` : '独立线路'} / ${routing.value === 'orthogonal' ? '正交折线' : '直线'})`
160
+ actionText.value = startPointId.value
161
+ ? `开始连线:起点已指定为 ${startPointLabel.value},下一次点节点只选终点(${isChannel.value ? `通道 ${circuits.value} 回` : '独立线路'} / ${routing.value === 'orthogonal' ? '正交折线' : '直线'})`
162
+ : `开始连线:先点起点,再点终点(${isChannel.value ? `通道 ${circuits.value} 回` : '独立线路'} / ${routing.value === 'orthogonal' ? '正交折线' : '直线'})`
140
163
  pushLog('beginAddChannel', actionText.value)
141
164
  }
142
165
 
@@ -177,6 +200,60 @@ const commitDraft = () => {
177
200
  emit('notice', actionText.value)
178
201
  }
179
202
 
203
+ /** 直接把本次新增的线路 / 通道对象交给 commitAddChannel:不再先 addLine / addChannel */
204
+ const commitWithObject = () => {
205
+ if (!view || !canFinish.value) {
206
+ return
207
+ }
208
+ const current = view.getAddChannelDraft()
209
+ if (!current?.from || !current?.to) {
210
+ return
211
+ }
212
+ sequence += 1
213
+ const from = current.from.id
214
+ const to = current.to.id
215
+ const middle = middlePathOf(current)
216
+ const fullPath = fullPathOf(current)
217
+ let payload
218
+ if (current.kind === 'line') {
219
+ payload = {
220
+ id: `connect-object-line-${sequence}`,
221
+ name: `对象线路 ${sequence}`,
222
+ from,
223
+ to,
224
+ ...(fullPath ? { path: fullPath } : {}),
225
+ ...currentLineProps()
226
+ }
227
+ }
228
+ else {
229
+ const lineIds = Array.from({ length: current.circuits }, (_item, index) => `connect-object-line-${sequence}-${index + 1}`)
230
+ const channelId = `connect-object-channel-${sequence}`
231
+ payload = {
232
+ id: channelId,
233
+ name: `对象通道 ${sequence}`,
234
+ from,
235
+ to,
236
+ lineIds,
237
+ ...(middle ? { path: middle } : {}),
238
+ groups: [{ id: channelId, lineIds, ...(middle ? { path: middle } : {}) }]
239
+ }
240
+ }
241
+ const result = view.commitAddChannel(payload)
242
+ refreshState()
243
+ if (!result.ok) {
244
+ actionText.value = `commitAddChannel(对象) 没有落地:${result.reason ?? '未知原因'}`
245
+ }
246
+ else {
247
+ const lines = result.lines?.length ?? (result.line ? 1 : 0)
248
+ actionText.value = `commitAddChannel(对象) → ${result.kind === 'line' ? '线路对象' : '通道对象'} ${String(result.channelId ?? result.lineId ?? '')} · ${lines} 回线`
249
+ if (result.lineIds?.length) {
250
+ view.selectFeatures(result.lineIds)
251
+ }
252
+ }
253
+ pushLog('commitAddChannel(对象)', actionText.value)
254
+ emit('notice', actionText.value)
255
+ }
256
+
180
257
  const middlePathOf = current => (current.path?.length ? current.path.map(point => [point[0], point[1]]) : null)
181
258
  const fullPathOf = current => {
182
259
  const middle = middlePathOf(current)
@@ -267,7 +344,7 @@ const resetScene = () => {
267
344
  pushLog('reset', actionText.value)
268
345
  }
269
346
 
270
- watch([lineColor, lineWidth, arrow, arrowSize, arrowPositionsText, circuitSpacing], () => {
347
+ watch([lineColor, lineWidth, arrow, arrowSize, arrowPositionsText, circuitSpacing, dotsVisible, dotSize, startDotColor, endDotColor, dotShape, draftLayer], () => {
271
348
  if (view && isDraftLive.value) {
272
349
  view.updateAddChannelStyle(currentDraftStyle())
273
350
  draft.value = view.getAddChannelDraft()
@@ -333,6 +410,14 @@ onBeforeUnmount(() => {
333
410
  </select>
334
411
  </label>
335
412
  </div>
413
+ <div class="dv-row">
414
+ <label>指定起点
415
+ <select v-model="startPointId" data-demo="connect-start-point" :disabled="isDraftLive">
416
+ <option value="">点击时再选</option>
417
+ <option v-for="point in points" :key="String(point.id)" :value="String(point.id)">{{ point.name ?? point.id }}</option>
418
+ </select>
419
+ </label>
420
+ </div>
336
421
  <div class="dv-row">
337
422
  <label>线色 <input v-model="lineColor" type="color" data-demo="connect-color" /></label>
338
423
  <label>线宽 <input v-model.number="lineWidth" type="range" min="1" max="6" step="0.2" data-demo="connect-width" /> {{ lineWidth.toFixed(1) }}</label>
@@ -356,6 +441,31 @@ onBeforeUnmount(() => {
356
441
  <p class="dv-hint">草稿样式直接传给 <code>beginAddChannel({ channelDraftStyle })</code>;连线期间改颜色 / 线宽 / 箭头位置 / 回线间距会走 <code>updateAddChannelStyle()</code>,预览立即更新。正交折线会自动补一个 90 度拐点;落地线路用完整 path,通道只写中间拐点。</p>
357
442
  </div>
358
443
 
444
+ <div class="dv-group">
445
+ <h3>示例点与层级</h3>
446
+ <div class="dv-row">
447
+ <label><input v-model="dotsVisible" type="checkbox" data-demo="connect-dots-visible" /> 显示两端示例点</label>
448
+ <label>形状
449
+ <select v-model="dotShape" data-demo="connect-dot-shape">
450
+ <option value="circle">圆形</option>
451
+ <option value="square">方形</option>
452
+ </select>
453
+ </label>
454
+ <label>尺寸 <input v-model.number="dotSize" type="range" min="2" max="12" step="1" data-demo="connect-dot-size" /> {{ dotSize }}px</label>
455
+ </div>
456
+ <div class="dv-row">
457
+ <label>起点色 <input v-model="startDotColor" type="color" data-demo="connect-dot-from-color" :disabled="!dotsVisible" /></label>
458
+ <label>终点色 <input v-model="endDotColor" type="color" data-demo="connect-dot-to-color" :disabled="!dotsVisible" /></label>
459
+ <label>示例线路层级
460
+ <select v-model="draftLayer" data-demo="connect-draft-layer">
461
+ <option value="above">真实节点之上</option>
462
+ <option value="below-points">真实节点之下</option>
463
+ </select>
464
+ </label>
465
+ </div>
466
+ <p class="dv-hint">示例点始终落在被点击节点的正中心(多回线偏移不会带走它),可通过 <code>dots: false</code> 关闭,或用 <code>dots.from / dots.to</code> 分别配颜色、尺寸与形状。层级只作用于示例线 / 箭头 / <code>customDraw</code>;示例点仍画在真实节点之后,保证看得见。</p>
467
+ </div>
468
+
359
469
  <div class="dv-group">
360
470
  <h3>草稿与落地</h3>
361
471
  <div class="dv-row">
@@ -364,6 +474,7 @@ onBeforeUnmount(() => {
364
474
  </div>
365
475
  <div class="dv-row">
366
476
  <button type="button" class="dv-button" data-demo="connect-default" :disabled="!canFinish" @click="commitDraft">默认添加(commitAddChannel)</button>
477
+ <button type="button" class="dv-button" data-demo="connect-commit-object" :disabled="!canFinish" @click="commitWithObject">对象提交(通道 / 线路对象)</button>
367
478
  <button type="button" class="dv-button" data-demo="connect-add-lines" :disabled="!canFinish" @click="addWithLines">用 addLines 添加</button>
368
479
  <button type="button" class="dv-button" data-demo="connect-add-channels" :disabled="!canFinish" @click="addWithChannels">用 addChannels 添加</button>
369
480
  </div>
@@ -17,12 +17,17 @@ const enabled = ref(true)
17
17
  const size = ref('medium')
18
18
  const position = ref('bottom-right')
19
19
  const extent = ref('auto')
20
- const ruleMode = ref('voltage')
20
+ const ruleMode = ref('inherit')
21
21
  const levelMode = ref('all')
22
- const linkedSizes = ref(true)
22
+ const pointSizeScale = ref(1)
23
+ const lineWidthScale = ref(1)
24
+ const pointZoomScale = ref(0)
25
+ const lineZoomScale = ref(0)
23
26
  const channelCircuits = ref(true)
24
- const zoomable = ref(true)
27
+ const zoomMode = ref('manual')
28
+ const followZoomScale = ref(1)
25
29
  const dragAction = ref('pan')
30
+ const extentFollowCamera = ref(false)
26
31
  const maxPixelRatio = ref('2')
27
32
  const gridPlacement = ref('below-data')
28
33
  const customLayers = ref(true)
@@ -125,6 +130,7 @@ const minimapOptions = () => {
125
130
  margin: 12,
126
131
  padding: 0.05,
127
132
  extent: extent.value,
133
+ extentFollowCamera: extentFollowCamera.value,
128
134
  background: 'inherit',
129
135
  backgroundStyle: 'rgba(255, 255, 255, 0.94)',
130
136
  borderColor: '#c7d8eb',
@@ -140,16 +146,19 @@ const minimapOptions = () => {
140
146
  levels: levelMode.value === 'top' ? [2] : undefined,
141
147
  cascade: 'both',
142
148
  layered: true,
143
- pointSizeScale: 1,
144
- lineWidthScale: 1,
145
- pointMapZoomScale: linkedSizes.value ? 0.5 : 0,
146
- lineMapZoomScale: linkedSizes.value ? 0.5 : 0,
149
+ // 自己规则 / 沿用主图都乘这一份;与主图相机倍数、小图自身倍数都无关
150
+ pointSizeScale: Number(pointSizeScale.value),
151
+ lineWidthScale: Number(lineWidthScale.value),
152
+ // 只有小图自身放大时才按这两个指数联动;沿用主图的节点 / 线路也一样
153
+ pointZoomScale: Number(pointZoomScale.value),
154
+ lineZoomScale: Number(lineZoomScale.value),
147
155
  boxStyle: { fill: '#3678bf', fillOpacity: 0.16, stroke: '#3678bf', strokeWidth: 1, strokeStyle: 'dashed', radius: 3 },
148
156
  selectStyle: { fill: '#f0a43c', stroke: '#f0a43c' },
149
157
  interactive: true,
150
158
  onInteraction: handleMinimapInteraction,
151
159
  longPressDelay: 180,
152
- zoomable: zoomable.value,
160
+ zoomable: zoomMode.value === 'manual' ? true : zoomMode.value === 'follow' ? 'follow' : false,
161
+ followZoomScale: Number(followZoomScale.value),
153
162
  minZoom: 0.7,
154
163
  maxZoom: 6,
155
164
  zoomStep: 1.35,
@@ -168,10 +177,14 @@ const refreshReadout = () => {
168
177
  const sizeText = root ? `${Math.round(root.getBoundingClientRect().width)}×${Math.round(root.getBoundingClientRect().height)}` : '未挂载'
169
178
  readout.value = `${sizeText} · 备份 ${canvas?.width ?? 0}×${canvas?.height ?? 0} · 像素比 ${ratio ? ratio.toFixed(2) : '—'} · 范围 ${extent.value} · 自定义层 ${options.layers.length}`
170
179
  if (view) {
171
- zoomReadout.value = `小图倍数 ${view.getMinimapZoom().toFixed(2)} · ${zoomable.value ? '滚轮缩放小图' : '滚轮缩放主图'}`
180
+ zoomReadout.value = `小图倍数 ${view.getMinimapZoom().toFixed(2)} · ${zoomModeLabel.value}`
172
181
  }
173
182
  }
174
183
 
184
+ const zoomModeLabel = computed(() => zoomMode.value === 'manual'
185
+ ? '手动缩放小图'
186
+ : zoomMode.value === 'follow' ? `跟随主图(指数 ${Number(followZoomScale.value).toFixed(1)})` : '不缩放小图,滚轮缩放主图')
187
+
175
188
  const applyMinimap = () => {
176
189
  if (!view) {
177
190
  return
@@ -193,10 +206,20 @@ const zoomMinimap = (factor) => {
193
206
 
194
207
  const refreshZoom = () => {
195
208
  if (view) {
196
- zoomReadout.value = `小图倍数 ${view.getMinimapZoom().toFixed(2)} · ${zoomable.value ? '滚轮缩放小图' : '滚轮缩放主图'}`
209
+ zoomReadout.value = `小图倍数 ${view.getMinimapZoom().toFixed(2)} · ${zoomModeLabel.value}`
197
210
  }
198
211
  }
199
212
 
213
+ /** 拖拽演示:框选不依赖 zoomable;平移才需要手动缩放后内容有可移动余量 */
214
+ const showDragDemo = (action) => {
215
+ dragAction.value = action
216
+ zoomMode.value = action === 'box' ? 'off' : 'manual'
217
+ applyMinimap()
218
+ eventText.value = action === 'box'
219
+ ? '拖拽演示:缩放模式已关闭,在小图空白处直接拖动仍能拉出框选矩形'
220
+ : '拖拽演示:已切到手动缩放,在小图空白处拖动平移小图内容'
221
+ }
222
+
200
223
  const refreshLayerReadout = () => {
201
224
  layerReadout.value = `网格层 ${layerPaints.grid} 次(${layerPaints.gridStage}) · 指北针层 ${layerPaints.compass} 次`
202
225
  refreshReadout()
@@ -289,6 +312,9 @@ const sizeSummary = computed(() => `${SIZES[size.value]?.[0] ?? 0}×${SIZES[size
289
312
  </select>
290
313
  </label>
291
314
  </div>
315
+ <div class="dv-row">
316
+ <label><input v-model="extentFollowCamera" type="checkbox" data-demo="minimap-extent-follow" @change="applyMinimap" /> 自动范围随相机收窄(默认关)</label>
317
+ </div>
292
318
  <p class="dv-hint"><code>maxPixelRatio</code> 越大越清晰,也越吃填充率;高分屏按机器档位调到 2 通常就够。</p>
293
319
  </div>
294
320
  <div class="dv-group">
@@ -309,11 +335,24 @@ const sizeSummary = computed(() => `${SIZES[size.value]?.[0] ?? 0}×${SIZES[size
309
335
  </label>
310
336
  </div>
311
337
  <div class="dv-row">
312
- <label><input v-model="linkedSizes" type="checkbox" data-demo="minimap-linked" @change="applyMinimap" /> 尺寸跟随主图缩放</label>
338
+ <label>节点整体倍数 <input v-model.number="pointSizeScale" type="range" min="0" max="3" step="0.1" data-demo="minimap-point-size-scale" @change="applyMinimap" /> {{ Number(pointSizeScale).toFixed(1) }}</label>
339
+ <label>线路整体倍数 <input v-model.number="lineWidthScale" type="range" min="0" max="3" step="0.1" data-demo="minimap-line-width-scale" @change="applyMinimap" /> {{ Number(lineWidthScale).toFixed(1) }}</label>
340
+ </div>
341
+ <div class="dv-row">
342
+ <label>小图放大节点 <input v-model.number="pointZoomScale" type="range" min="0" max="1" step="0.1" data-demo="minimap-point-zoom-scale" @change="applyMinimap" /> {{ Number(pointZoomScale).toFixed(1) }}</label>
343
+ <label>小图放大线路 <input v-model.number="lineZoomScale" type="range" min="0" max="1" step="0.1" data-demo="minimap-line-zoom-scale" @change="applyMinimap" /> {{ Number(lineZoomScale).toFixed(1) }}</label>
344
+ </div>
345
+ <div class="dv-row">
313
346
  <label><input v-model="channelCircuits" type="checkbox" data-demo="minimap-circuits" @change="applyMinimap" /> 画全部回线</label>
314
347
  </div>
315
348
  <div class="dv-row">
316
- <label><input v-model="zoomable" type="checkbox" data-demo="minimap-zoomable" @change="applyMinimap" /> 小图自身可缩放</label>
349
+ <label>缩放模式
350
+ <select v-model="zoomMode" data-demo="minimap-zoomable" @change="applyMinimap">
351
+ <option value="off">关闭</option>
352
+ <option value="manual">手动缩放小图</option>
353
+ <option value="follow">跟随主图</option>
354
+ </select>
355
+ </label>
317
356
  <label>空白拖动
318
357
  <select v-model="dragAction" data-demo="minimap-drag-action" @change="applyMinimap">
319
358
  <option value="pan">平移小图</option>
@@ -321,7 +360,14 @@ const sizeSummary = computed(() => `${SIZES[size.value]?.[0] ?? 0}×${SIZES[size
321
360
  </select>
322
361
  </label>
323
362
  </div>
324
- <p class="dv-hint">打开「小图自身可缩放」后,滚轮缩放小图;按住 Ctrl / ⌘ + 滚轮仍然缩放主图。视口框可以拖,空白处长按跟随。</p>
363
+ <div class="dv-row">
364
+ <label>跟随指数 <input v-model.number="followZoomScale" type="range" min="0" max="2" step="0.1" data-demo="minimap-follow-scale" @change="applyMinimap" /> {{ Number(followZoomScale).toFixed(1) }}</label>
365
+ </div>
366
+ <div class="dv-row">
367
+ <button type="button" class="dv-button" data-demo="minimap-drag-box" @click="showDragDemo('box')">拖拽演示:框选</button>
368
+ <button type="button" class="dv-button" data-demo="minimap-drag-pan" @click="showDragDemo('pan')">拖拽演示:平移</button>
369
+ </div>
370
+ <p class="dv-hint">沿用主图规则时,节点 / 线路先按「小图视口 ÷ 主图视口」缩放,主图放大缩小不会改变它们的大小;滚轮或 + / - 放大鹰眼图时,再按 <code>pointZoomScale</code> / <code>lineZoomScale</code> 的指数变化。两个整体倍数对自有规则与沿用主图的要素都生效。<code>zoomable: true</code> 是小图手动缩放,<code>'follow'</code> 是整体范围跟随主图,两者互斥;<code>followZoomScale</code> 是主图倍数的指数。框选不依赖缩放开关:选「关闭」+ <code>dragAction: 'box'</code>,空白处拖动仍会直接框选。视口框可以拖,空白处长按跟随。</p>
325
371
  </div>
326
372
  <div class="dv-group">
327
373
  <h3>扩展层</h3>
@@ -341,9 +387,9 @@ const sizeSummary = computed(() => `${SIZES[size.value]?.[0] ?? 0}×${SIZES[size
341
387
  <div class="dv-group">
342
388
  <h3>小图倍数</h3>
343
389
  <div class="dv-row">
344
- <button type="button" class="dv-button" data-demo="minimap-zoom-out" @click="zoomMinimap(1 / 1.35)">-</button>
345
- <button type="button" class="dv-button dv-button--primary" data-demo="minimap-zoom-reset" @click="resetZoom">1×</button>
346
- <button type="button" class="dv-button" data-demo="minimap-zoom-in" @click="zoomMinimap(1.35)">+</button>
390
+ <button type="button" class="dv-button" data-demo="minimap-zoom-out" :disabled="zoomMode === 'follow'" @click="zoomMinimap(1 / 1.35)">-</button>
391
+ <button type="button" class="dv-button dv-button--primary" data-demo="minimap-zoom-reset" :disabled="zoomMode === 'follow'" @click="resetZoom">1×</button>
392
+ <button type="button" class="dv-button" data-demo="minimap-zoom-in" :disabled="zoomMode === 'follow'" @click="zoomMinimap(1.35)">+</button>
347
393
  </div>
348
394
  <p class="dv-readout" data-demo="minimap-zoom-readout">{{ zoomReadout }}</p>
349
395
  </div>