gis-view-webgl2 0.1.6 → 0.1.7
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.
- package/README.md +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +86 -7
- package/dist/index.js +1 -1
- package/docs/AI/345/257/271/350/257/235/346/261/207/346/200/273.md +57 -0
- package/docs/GisView.md +1 -1
- 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 +62 -0
- package/docs/demos/LabelDemo.vue +2 -2
- package/docs/demos/StyleDemo.vue +1 -1
- package/docs/demos/api-index.js +8 -7
- package/docs/demos/gis-view-demo/useGisViewDemo.js +2 -2
- package/docs/manual/04-/344/272/213/344/273/266/344/270/216/345/233/236/350/260/203.md +36 -8
- 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 +7 -6
- package/docs/manual/08-/351/200/211/344/270/255/344/270/216/346/213/220/347/202/271.md +59 -3
- package/docs/manual/09-/351/200/232/351/201/223/344/270/216/345/244/232/345/233/236/347/272/277.md +14 -1
- 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
- package/docs/manual/17-/345/217/202/346/225/260/351/200/237/346/237/245.md +7 -6
- package/docs/manual/18-/351/200/220/346/226/271/346/263/225/347/244/272/344/276/213.md +7 -1
- package/docs/manual/20-/346/200/247/350/203/275/344/270/216/345/244/247/346/225/260/346/215/256.md +1 -0
- package/docs/steps/README.md +4 -4
- package/docs/steps/selftest-demos.html +2 -2
- package/docs/steps/selftest-docs.html +3 -3
- package/docs/steps/selftest-features.html +1 -1
- package/docs/steps/selftest-select.html +168 -1
- package/package.json +1 -1
|
@@ -473,3 +473,60 @@
|
|
|
473
473
|
- **正确性回归**:`selftest-perf.html` 新增 1 条像素级对拍,在同一交互状态下比较细线专用管线与四边形画法的线像素数量和整幅颜色差,防止新管线画丢、画黑或换色;新增断言与既有断言均通过。
|
|
474
474
|
- **核心文件**:`src/gis-view/shaders.js`、`src/gis-view/engine.js`、`docs/steps/selftest-perf.html`、`docs/steps/README.md`、`docs/manual/03-配置项.md`、`docs/manual/05-画质与批量更新.md`、`docs/manual/20-性能与大数据.md`、`docs/manual/21-说明与常见问题.md`、`docs/internals/18-性能实测与WebGPU评估.md`、根 `README.md`、`src/gis-view/README.md` 与本轮 aimd。
|
|
475
475
|
- **验证**:`node --check src/gis-view/engine.js`、`node --check src/gis-view/shaders.js`、`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs`(264 个实例成员未变)、`npm run check:docs`(264 个实例成员 / 250 个方法 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关)、九个定向自测页 **1504** 条通过 / 0 失败、`npm run build` 与 `git diff --check` 全部通过。`selftest-perf` **182 / 1**(共 183 条;标签读数 1313 次、重复 0 条,HEAD 基线已复现),新增像素断言通过;`selftest-scale` 117 / 2(既有的 onFilter 计数失败,筛选链路未改)。公开实例成员、options 与数据字段计数未变。复查入口见 [06 的增量记录](ai/06-会话索引与复查方法.md#2026-10-26-增量修改txt线片段着色管线专用化)。
|
|
476
|
+
|
|
477
|
+
## 2026-10-26 增量(「修改.txt」:选中 / 取消选中入口速查)
|
|
478
|
+
|
|
479
|
+
本轮仍是现有会话的继续增量,没有新建会话归档,因此不改上表的 39 条会话统计。需求原话来自仓库根目录最新的 `修改.txt`:修改 gis-view 组件;现在组件如何选中和取消选中。
|
|
480
|
+
|
|
481
|
+
- **现状核对**:公开入口只有 `selectFeatures(refs, options?)` 与 `deselect(refs?)`,`select()` 已在重复入口收口时删除。鼠标单选、Ctrl / ⌘ 取反、`multiSelect`、`boxSelect`、空白点击 / Esc 清空,以及接口替换 / 追加 / 取反 / 移除 / 清空都已存在,因此没有新增重复方法。
|
|
482
|
+
- **文档改动**:`docs/manual/08-选中与拐点.md` 顶部新增「选中与取消选中速查」,把鼠标 / 键盘 / 接口入口、`selectTrigger: 'dblClick'` 的差异、读回方法与 `onSelectChange` 放在一处;同时修正正文与当前 demo / 自测注释里的过期 `select()` 名称。
|
|
483
|
+
- **核心文件**:`docs/manual/08-选中与拐点.md`、`docs/demos/StyleDemo.vue`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`docs/steps/selftest-features.html`、`docs/AI对话汇总.md`、`docs/ai/06-会话索引与复查方法.md`。
|
|
484
|
+
- **验证**:`node docs/steps/gen-api-index.mjs --check`(生成索引最新)、`npm run check:docs`(264 个实例成员 / 250 个方法 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关全部命中)、`npx tsc --noEmit`、`npm run build`、`selftest-select.html` **69** 条通过 / 0 失败,以及 `git diff --check` 全部通过。公开 API 计数未变。
|
|
485
|
+
## 2026-10-26 增量(「修改.txt」:按坐标模拟单击选中 selectAt)
|
|
486
|
+
|
|
487
|
+
本轮仍是现有会话的继续增量,没有新建会话归档,因此不改上表的 39 条会话统计。需求原话来自仓库根目录最新的 `修改.txt`:「修改gis-view组件 1、我说的选中是手动触发单击选中,比如手动选中某个节点,某个通道,线路等,组件有这个方法吗」。
|
|
488
|
+
|
|
489
|
+
- **结论**:已有 `selectFeatures(refs, options?)` 可按 id / 下标 / `{ type, index }` 手动选中节点、线路、通道;`pickAt()` 只读命中、不改选中。为「拿鼠标坐标当一次单击」,本轮新增 `selectAt(clientX, clientY)`,没有恢复已删除的 `select()`。
|
|
490
|
+
- **行为**:`selectAt` 按真实单击相同的 `pick()` 顺序命中节点 / 线路并立即调用 `applySelection`;通道回线按 `channelSelectMode` 摊成一条 / 一组 / 整条通道。空白或聚合圆返回 `null`,不清空原选中;不等待 `selectTrigger: 'dblClick'`,也不派发 `onClick` / `onDblClick`,但 `onSelect` / `onSelectChange` 正常发,`cause` 为 `api`。
|
|
491
|
+
- **设计取舍**:这是接口入口,固定替换当前选中集;追加 / 取反仍用 `selectFeatures(refs, { mode: 'add' | 'toggle' })`。要清空仍用 `deselect()` / `selectFeatures(null)`。返回值为 `GisViewSelectPayload | null`。
|
|
492
|
+
- **核心文件**:`src/gis-view/create.js`、`src/gis-view/engine.js`、`src/gis-view/types.d.ts`、`docs/steps/selftest-select.html`、`docs/manual/08-选中与拐点.md`、`docs/manual/09-通道与多回线.md`、`docs/manual/16-实例方法总表.md`、`docs/manual/17-参数速查.md`、`docs/manual/18-逐方法示例.md`、`README.md`、`docs/GisView.md`、`docs/steps/README.md`、`docs/steps/selftest-docs.html`、`docs/steps/selftest-demos.html`、`docs/demos/api-index.js`(生成物)与本轮 aimd。
|
|
493
|
+
- **验证**:`node --check src/gis-view/create.js`、`node --check src/gis-view/engine.js`、`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(265 个实例成员 = 260 个方法 + 5 个属性 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关全部命中)、`selftest-select.html` **73** 条、`selftest-docs.html` **134** 条、`selftest-demos.html` **365** 条,三页共 **572** 条通过 / 0 失败;`npm run build` 与 `git diff --check` 全部通过。详细口径见 [06 的增量记录](ai/06-会话索引与复查方法.md#2026-10-26-增量修改txt按坐标模拟单击选中-selectat)。
|
|
494
|
+
## 2026-10-26 增量(「修改.txt」:选中接口的回调口径)
|
|
495
|
+
|
|
496
|
+
本轮仍是现有会话的继续增量,没有新建会话归档,因此不改上表的 39 条会话统计。需求原话来自仓库根目录最新的 `修改.txt`:「修改gis-view组件 1、selectFeatures为什么不会触发onSelect事件,也会将内容标记为选中的样式,不是选中吗,新增的selectAt和selectFeatures有什么区别」。
|
|
497
|
+
|
|
498
|
+
- **结论**:`selectFeatures()` / `deselect()` 确实会改同一份选中 state,选中样式、`isSelected()` 与 `getSelectionData()` 立即更新;它们属于按引用改选中集的接口路径,只发 `onSelectChange`(`cause: 'api'`),不补发点击 / 框选语义的 `onSelect`。`selectAt()` 是明确的「按坐标模拟单击」,因此同时发 `onSelect` 与 `onSelectChange`,但不发 `onClick` / `onDblClick`。
|
|
499
|
+
- **事件口径**:`onSelectChange` 覆盖点击、框选、键盘清空与接口调用,并且只在选中集真的变化时发,适合统一同步面板;`onSelect` 覆盖点击 / 框选语义(真实点击 / Ctrl 多选 / 框选(含 `selectInBox()`)/ 空白清空)与模拟单击的 `selectAt()`。此前手册 17 把 `selectFeatures` 写成也会发 `onSelect`,与实际行为不一致,已改正。
|
|
500
|
+
- **两个方法的区别**:`selectAt(clientX, clientY)` 吃坐标、走与真实单击相同的 `pick()`,通道回线按 `channelSelectMode` 摊开,空白返回 `null` 且不动原选中,返回本次载荷;`selectFeatures(refs, options)` 吃 id / 下标 / 通道 / 分组引用,`mode` 支持 replace / add / toggle / remove,`null` / 空数组清空,返回实例本身。两者最终改的是同一份选中 state,样式与读数没有区别。
|
|
501
|
+
- **核心文件**:`docs/manual/04-事件与回调.md`、`docs/manual/08-选中与拐点.md`、`docs/manual/16-实例方法总表.md`、`docs/manual/17-参数速查.md`、`docs/manual/18-逐方法示例.md`、`src/gis-view/types.d.ts`、`docs/steps/selftest-select.html`、`docs/steps/README.md`、`docs/demos/api-index.js`(生成物)与本轮 aimd。
|
|
502
|
+
- **验证**:`selftest-select.html` 新增 2 条事件口径断言(73 → **75**),三页定向自测 **574** 条通过 / 0 失败(select 75 / docs 134 / demos 365);`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(265 个实例成员 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关全部命中)、`npm run build` 与 `git diff --check` 全部通过。运行时代码与公开成员计数未变。详细口径见 [06 的增量记录](ai/06-会话索引与复查方法.md#2026-10-26-增量修改txt选中接口的回调口径)。
|
|
503
|
+
|
|
504
|
+
## 2026-10-26 增量(「修改.txt」:统一选中回调与鼠标分组载荷)
|
|
505
|
+
|
|
506
|
+
本轮仍是现有会话的继续增量,没有新建会话归档,因此不改上表的 39 条会话统计。需求原话来自仓库根目录最新的 `修改.txt`:「修改gis-view组件 1、选中指的不就是点击触发select的选中吗,什么叫真正的选中 2、那先selectFeatures有什么用,我想直接通过方法选中一个节点如何操作,用selectAt传坐标,不多余吗?3、鼠标事件里的groups怎么没」。
|
|
507
|
+
|
|
508
|
+
- **选中语义统一**:点击、框选与 `selectFeatures()` / `deselect()` / `selectAt()` 现在共用同一份选中 state,实际改变选中集时都从组件级 `handleSelectPayload(payload, detail)` 发出 `onSelect` 与 `onSelectChange`;接口来源的 `cause` 仍是 `'api'`,原样重设同一选中集只同步镜像与读数、不重复发回调。`selectAt()` 只解决「手上只有客户端坐标」这一种场景:走与单击相同的 `pick()`,立即生效但不派发 `onClick` / `onDblClick`;已知节点 / 线路 id 时直接 `selectFeatures('id')` 或传引用。上一轮「接口只发 onSelectChange」的章节保留为历史,本轮口径已取代它。
|
|
509
|
+
- **鼠标事件分组载荷**:通道回线最终命中时,拾取结果除 `group`(当前组)外补 `groups`(同一通道全部分组,按声明顺序,每项带 `groupIndex` / `lineIds` / `path` 与成员 / 拐点读数)。`pickAt()`、`hoverAt()` / `onHover`、`onPointerDown` / `onPointerUp`、`onClick` / `onDblClick`、`onContextMenu` 都是同一份;全部分组只在最终命中后构建,悬停扫描过程中不复制成员数组。
|
|
510
|
+
- **核心文件**:`src/gis-view/create.js`、`src/gis-view/engine.js`、`src/gis-view/types.d.ts`、`docs/steps/selftest-select.html`、`docs/manual/04-事件与回调.md`、`07-指针与要素编辑.md`、`08-选中与拐点.md`、`09-通道与多回线.md`、`16-实例方法总表.md`、`17-参数速查.md`、`18-逐方法示例.md`、`src/gis-view/README.md`、`docs/steps/README.md`、`docs/demos/api-index.js`(生成物)与本轮 aimd。
|
|
511
|
+
- **验证**:`node --check src/gis-view/create.js`、`node --check src/gis-view/engine.js`、`npx tsc --noEmit`;四页定向自测 **1250** 条通过 / 0 失败(select 79 / features 672 / docs 134 / demos 365);`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(265 个实例成员 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关全部命中);`npm run build` 与 `git diff --check` 通过(后者仅有 CRLF 提示)。详细口径见 [06 的增量记录](ai/06-会话索引与复查方法.md#2026-10-26-增量修改txt统一选中回调与鼠标分组载荷)。
|
|
512
|
+
|
|
513
|
+
## 2026-10-26 增量(「修改.txt」:选中事件分工、通道上下文与派发顺序)
|
|
514
|
+
|
|
515
|
+
本轮仍是现有会话的继续增量,没有新建会话归档,因此不改上表的 39 条会话统计。需求原话来自仓库根目录最新的 `修改.txt`:「修改gis-view组件 1、onSelectChange和onSelect有必要同时存在吗,各自的意义是什么 2、为什么这两个事件里都拿不到通道的信息,group和groups都没有,隐藏这两个参数的意义是什么 3、为什么控制台顺序onSelectChange>onSelect>onClick」。
|
|
516
|
+
|
|
517
|
+
- **两个事件的职责**:保留 `onSelect` 与 `onSelectChange`。`onSelect` 是**本次选中操作**回调:真实单击 / Ctrl / `multiSelect` 取反 / 框选 / `selectAt()` 每次成功操作都发,清空或取反取没了时载荷为 `null`;`selectFeatures()` / `deselect()` / `focusOn({ select })` 等按引用接口只在实际改变选中集时发。`onSelectChange` 是**选中集合状态**回调:所有来源都只在实际变化时发,带 `ids` / `count` / 类型计数 / `cause` / `action`,需要统一同步面板时只订阅它。
|
|
518
|
+
- **通道上下文**:两条选中回调现在带同一套上下文。选中集只涉及一条通道时顶层平铺 `channelId` / `channelIndex` / `channel` / `groupId` / `groupIndex` / `group` / `groups`;多条通道时只给 `channelContexts`,每项带同样字段与本次选中的 `lineIndexes` / `lineIds`。`items[]` 里的通道回线也补 `group` / `groups`。真实单击与 `selectAt()` 的当前组是命中的那一组;框选 / 按引用选中取选中集里第一条通道回线所在的组;`groups` 始终是整条通道的全部分组。
|
|
519
|
+
- **派发顺序**:旧顺序 `onSelectChange → onSelect → onClick` 改为固定 `onClick → onSelect → onSelectChange`。普通单击由组件层 `deferredSelection` 只延后选中回调、先同步选中镜像与标签,等 `onClick` 派发后再补 `onSelect` / `onSelectChange`;Ctrl / `multiSelect` 取反、框选与接口选中没有 `onClick`,顺序为 `onSelect → onSelectChange`;双击模式第二下为 `onClick → onSelect → onSelectChange(有变化时)→ onDblClick`。回调里读 `getSelectionData()` 仍是最新值。
|
|
520
|
+
- **channelIndex 修正**:分组通道此前在拾取 / 悬停 / `describe` / `listLines` / 级联 / `getLineChannel` 等六处取了分组状态序号 `state.order`,与「通道在 `channels` 声明数组里的下标」不是一回事;现统一改为 `state.channelIndex`,通道增删或分组重排后读数不再漂移。
|
|
521
|
+
- **核心文件**:`src/gis-view/engine.js`、`src/gis-view/create.js`、`src/gis-view/types.d.ts`、`docs/steps/selftest-select.html`、`docs/manual/04-事件与回调.md`、`07-指针与要素编辑.md`、`08-选中与拐点.md`、`09-通道与多回线.md`、`16-实例方法总表.md`、`17-参数速查.md`、`18-逐方法示例.md`、`src/gis-view/README.md`、`docs/steps/README.md`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`docs/demos/api-index.js`(生成物)与本轮 aimd。
|
|
522
|
+
- **验证**:`node --check`(engine / create)、`npx tsc --noEmit`;`selftest-select.html` **83** 条、`selftest-features.html` **672** 条、`selftest-docs.html` **134** 条、`selftest-demos.html` **365** 条,四页共 **1254** 条通过 / 0 失败;`npm run build` 通过;`node docs/steps/gen-api-index.mjs --check` PASS(索引最新)、`npm run check:docs` 全 PASS(265 个实例成员 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关)、`git diff --check` 通过(仅有 CRLF 提示)。公开实例成员 / options / 数据字段 / 事件 / 功能开关计数均未变。
|
|
523
|
+
|
|
524
|
+
## 2026-10-26 增量(「修改.txt」:选中载荷去重与通道索引缓存)
|
|
525
|
+
|
|
526
|
+
本轮仍是现有会话的继续增量,没有新建会话归档,因此不改上表的 39 条会话统计。需求原话来自仓库根目录最新的 `修改.txt`:「修改gis-view组件 1、本次修改会影响组件性能吗,比如事件参数添加group和groups,selectFeatures触发onSelect等,如果影响性能,如何优化 2、现在onSelect和onSelectChange参数都有通道信息,下面的items里面也有通道信息,是不是有些多余, 3、继续检查组件,有没有冗余代码,继续提高组件性能」。
|
|
527
|
+
|
|
528
|
+
- **性能结论**:选中事件不进入逐帧渲染路径,只在选中操作 / 选中集实际变化时构造;`onSelect` 与 `onSelectChange` 共享同一批 `items`、分组对象与数组引用,不深拷贝。`selectFeatures()` 仍只在集合实际变化时发事件,同内容、同顺序的重设现在会在 `selectionKeys()`、引擎刷新与 `describeSelection()` 之前直接返回;`selectAt()` 每次成功命中发 `onSelect` 是既定语义,开销只随本次选中的通道 / 分组数增长,不随全量点线数增长。
|
|
529
|
+
- **载荷去重**:单通道只把 `channelId` / `channelIndex` / `channel` / `groupId` / `groupIndex` / `group` / `groups` 摊平到载荷顶层,不再额外创建 `channelContexts`;多通道才给 `channelContexts`。`items[]` 里的通道回线只保留 `channelId` / `channelIndex` / `groupId` / `groupIndex` 标量归属,不再逐条挂 `group` / `groups`,分组读数统一从顶层或 `channelContexts` 取。指针事件载荷保持原样,不受这条限制。上一节“items 里的通道回线也补 group / groups”的口径由本节撤回。
|
|
530
|
+
- **冗余与性能**:通道重建时按 `channelIndex` 同步收好分组状态数组,并把 `groupOrdinal` 直接记在通道状态上;`channelSiblings()` / `channelGroupOrdinal()` 从扫整张通道表降为 O(1),构造一条通道的全部分组读数从 O(组数 × 通道数) 降为 O(组数)。选中上下文按已记录的组序号取当前组,不再 `findIndex`;删掉已无引用的 `state.order` 和建通道时的重复 `channels.filter(...)`。单通道选中不再构造随后丢弃的 `lineIndexes` / `lineIds`,多通道才在 `channelContexts` 里按选中顺序补一次。
|
|
531
|
+
- **核心文件**:`src/gis-view/engine.js`、`src/gis-view/create.js`、`src/gis-view/types.d.ts`、`docs/steps/selftest-select.html`、`docs/steps/README.md`、`docs/manual/04-事件与回调.md`、`07-指针与要素编辑.md`、`09-通道与多回线.md`、`20-性能与大数据.md`、`src/gis-view/README.md` 与本轮 aimd。
|
|
532
|
+
- **验证**:`node --check`(engine / create)、`npx tsc --noEmit`、`npm run build` 通过;五页定向自测 **1438** 条通过 / 0 失败(select 84 / features 672 / docs 134 / demos 365 / perf 183);`node docs/steps/gen-api-index.mjs --check` PASS(索引最新)、`npm run check:docs` 全 PASS(265 个实例成员 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关)、`git diff --check` 通过(仅有 CRLF 提示)。公开实例成员与配置计数未变。
|
package/docs/GisView.md
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
| [14 视图与筛选](manual/14-视图与筛选.md) | 筛选、搜索定位、初始视图与缩放范围、背景层、鹰眼图、近义入口 |
|
|
33
33
|
| [15 导出与集成](manual/15-导出与集成.md) | 导出图片 / 选中节点 / 数据、自定义导出格式,插件、自建界面与键盘交互 |
|
|
34
34
|
| [16 实例方法总表](manual/16-实例方法总表.md) | 按功能分组的实例方法主表(找方法从这一章开始) |
|
|
35
|
-
| [17 参数速查(逐个方法)](manual/17-参数速查.md) |
|
|
35
|
+
| [17 参数速查(逐个方法)](manual/17-参数速查.md) | 265 个成员逐个列全:参数、默认值与返回 |
|
|
36
36
|
| [18 逐方法示例(复制就能跑)](manual/18-逐方法示例.md) | 每个成员一段可复制的调用示例(API 速查页读的就是这一章) |
|
|
37
37
|
| [19 读数与拖拽预览](manual/19-读数与拖拽预览.md) | 自建界面常用的读数 / 定位方法;拖拽落点预览 |
|
|
38
38
|
| [20 性能与大数据](manual/20-性能与大数据.md) | 十万级数据的开关与实测、WebGPU 取舍、渲染后端开关 |
|
|
@@ -448,6 +448,68 @@
|
|
|
448
448
|
- **实测**:10 万点 / 5 万线缩放 p50 **23.2 → 16.7 ms**、p95 **28.6 → 16.8 ~ 16.9 ms**;10 万点 / 10 万线缩放三次中位 p50 **42.6 → 18.0 ms**、p95 **46.3 → 21.4 ms**;2px 实线的 10 万线只走四边形轻量片元时约 **82.4 → 63.9 ms**。16 ~ 18 ms 已接近 60Hz 帧节拍,剩余成本是 GPU 填充率。
|
|
449
449
|
- **核心文件**:`src/gis-view/shaders.js`、`src/gis-view/engine.js`、`docs/steps/selftest-perf.html`、`docs/steps/README.md`、`docs/manual/03-配置项.md`、`docs/manual/05-画质与批量更新.md`、`docs/manual/20-性能与大数据.md`、`docs/manual/21-说明与常见问题.md`、`docs/internals/18-性能实测与WebGPU评估.md`、根 `README.md`、`src/gis-view/README.md` 与本轮 aimd。
|
|
450
450
|
- **验证**:`node --check`(engine / shaders)、`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs`(264 个实例成员未变)、`npm run check:docs`(264 个实例成员 / 250 个方法 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关)、九个定向自测页 **1504** 条通过 / 0 失败、`npm run build` 与 `git diff --check` 全部通过。`selftest-perf` **182 / 1**(共 183 条;新增像素对拍通过,标签读数失败在 HEAD 已复现);`selftest-scale` 117 / 2(既有 onFilter 计数失败)。公开 API 计数未变。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-26-增量修改txt继续优化-gis-view回答感觉没提升多少)。
|
|
451
|
+
|
|
452
|
+
### 2026-10-26 增量(「修改.txt」:选中 / 取消选中入口速查)
|
|
453
|
+
|
|
454
|
+
本轮仍是现有会话的继续增量,没有独立会话归档,因此不改上表的 39 条统计。需求原话来自仓库根目录最新的 `修改.txt`:修改 gis-view 组件;现在组件如何选中和取消选中。
|
|
455
|
+
|
|
456
|
+
- **结论**:公开入口只有 `selectFeatures(refs, options?)` 与 `deselect(refs?)`,没有 `select()`;现有鼠标、键盘、框选与接口路径已经覆盖选中 / 取消,不需要新增重复 API。
|
|
457
|
+
- **文档**:`docs/manual/08-选中与拐点.md` 顶部新增「选中与取消选中速查」,并修正当前正文、demo 与自测注释中把 `select()` 当现存接口的说法。
|
|
458
|
+
- **核心文件**:`docs/manual/08-选中与拐点.md`、`docs/demos/StyleDemo.vue`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`docs/steps/selftest-features.html`、`docs/AI对话汇总.md` 与本章。
|
|
459
|
+
- **验证**:`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(264 个实例成员 / 250 个方法 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关)、`npx tsc --noEmit`、`npm run build`、`selftest-select.html` **69** 条通过 / 0 失败,以及 `git diff --check` 全部通过;公开 API 计数未变。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-26-增量修改txt选中--取消选中入口速查)。
|
|
460
|
+
|
|
461
|
+
### 2026-10-26 增量(「修改.txt」:按坐标模拟单击选中 selectAt)
|
|
462
|
+
|
|
463
|
+
本轮仍是现有会话的继续增量,没有独立会话归档,因此不改上表的 39 条统计。需求原话来自仓库根目录最新的 `修改.txt`:「修改gis-view组件 1、我说的选中是手动触发单击选中,比如手动选中某个节点,某个通道,线路等,组件有这个方法吗」。
|
|
464
|
+
|
|
465
|
+
- **结论**:已有 `selectFeatures(refs, options?)` 可按 id / 下标 / `{ type, index }` 手动选中节点、线路、通道;`pickAt()` 只读命中、不改选中。为「拿鼠标坐标当一次单击」,本轮新增 `selectAt(clientX, clientY)`,没有恢复已删除的 `select()`。
|
|
466
|
+
- **行为**:`selectAt` 按真实单击相同的 `pick()` 顺序命中节点 / 线路并立即调用 `applySelection`;通道回线按 `channelSelectMode` 摊成一条 / 一组 / 整条通道。空白或聚合圆返回 `null`,不清空原选中;不等待 `selectTrigger: 'dblClick'`,也不派发 `onClick` / `onDblClick`,但 `onSelect` / `onSelectChange` 正常发,`cause` 为 `api`。
|
|
467
|
+
- **设计取舍**:这是接口入口,固定替换当前选中集;追加 / 取反仍用 `selectFeatures(refs, { mode: 'add' | 'toggle' })`。要清空仍用 `deselect()` / `selectFeatures(null)`。返回值为 `GisViewSelectPayload | null`。
|
|
468
|
+
- **核心文件**:`src/gis-view/create.js`、`src/gis-view/engine.js`、`src/gis-view/types.d.ts`、`docs/steps/selftest-select.html`、`docs/manual/08-选中与拐点.md`、`docs/manual/09-通道与多回线.md`、`docs/manual/16-实例方法总表.md`、`docs/manual/17-参数速查.md`、`docs/manual/18-逐方法示例.md`、`README.md`、`docs/GisView.md`、`docs/steps/README.md`、`docs/steps/selftest-docs.html`、`docs/steps/selftest-demos.html`、`docs/demos/api-index.js`(生成物)与本轮 aimd。
|
|
469
|
+
- **验证**:`node --check src/gis-view/create.js`、`node --check src/gis-view/engine.js`、`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(265 个实例成员 = 260 个方法 + 5 个属性 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关全部命中)、`selftest-select.html` **73** 条、`selftest-docs.html` **134** 条、`selftest-demos.html` **365** 条,三页共 **572** 条通过 / 0 失败;`npm run build` 与 `git diff --check` 全部通过。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-26-增量修改txt按坐标模拟单击选中-selectat)。
|
|
470
|
+
|
|
471
|
+
### 2026-10-26 增量(「修改.txt」:选中接口的回调口径)
|
|
472
|
+
|
|
473
|
+
本轮仍是现有会话的继续增量,没有独立会话归档,因此不改上表的 39 条统计。需求原话来自仓库根目录最新的 `修改.txt`:「修改gis-view组件 1、selectFeatures为什么不会触发onSelect事件,也会将内容标记为选中的样式,不是选中吗,新增的selectAt和selectFeatures有什么区别」。
|
|
474
|
+
|
|
475
|
+
- **结论**:`selectFeatures()` / `deselect()` 确实会改同一份选中 state,选中样式、`isSelected()` 与 `getSelectionData()` 立即更新;它们属于按引用改选中集的接口路径,只发 `onSelectChange`(`cause: 'api'`),不补发点击 / 框选语义的 `onSelect`。`selectAt()` 是明确的「按坐标模拟单击」,因此同时发 `onSelect` 与 `onSelectChange`,但不发 `onClick` / `onDblClick`。
|
|
476
|
+
- **事件口径**:`onSelectChange` 覆盖点击、框选、键盘清空与接口调用,并且只在选中集真的变化时发,适合统一同步面板;`onSelect` 覆盖点击 / 框选语义(真实点击 / Ctrl 多选 / 框选(含 `selectInBox()`)/ 空白清空)与模拟单击的 `selectAt()`。此前手册 17 把 `selectFeatures` 写成也会发 `onSelect`,与实际行为不一致,已改正。
|
|
477
|
+
- **两个方法的区别**:`selectAt(clientX, clientY)` 吃坐标、走与真实单击相同的 `pick()`,通道回线按 `channelSelectMode` 摊开,空白返回 `null` 且不动原选中,返回本次载荷;`selectFeatures(refs, options)` 吃 id / 下标 / 通道 / 分组引用,`mode` 支持 replace / add / toggle / remove,`null` / 空数组清空,返回实例本身。两者最终改的是同一份选中 state,样式与读数没有区别。
|
|
478
|
+
- **核心文件**:`docs/manual/04-事件与回调.md`、`docs/manual/08-选中与拐点.md`、`docs/manual/16-实例方法总表.md`、`docs/manual/17-参数速查.md`、`docs/manual/18-逐方法示例.md`、`src/gis-view/types.d.ts`、`docs/steps/selftest-select.html`、`docs/steps/README.md`、`docs/demos/api-index.js`(生成物)与本轮 aimd。
|
|
479
|
+
- **验证**:`selftest-select.html` 新增 2 条事件口径断言(73 → **75**),三页定向自测 **574** 条通过 / 0 失败(select 75 / docs 134 / demos 365);`npx tsc --noEmit`、`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(265 个实例成员 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关全部命中)、`npm run build` 与 `git diff --check` 全部通过。运行时代码与公开成员计数未变。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-26-增量修改txt选中接口的回调口径)。
|
|
480
|
+
|
|
481
|
+
### 2026-10-26 增量(「修改.txt」:统一选中回调与鼠标分组载荷)
|
|
482
|
+
|
|
483
|
+
本轮仍是现有会话的继续增量,没有独立会话归档,因此不改上表的 39 条统计。需求原话来自仓库根目录最新的 `修改.txt`:「修改gis-view组件 1、选中指的不就是点击触发select的选中吗,什么叫真正的选中 2、那先selectFeatures有什么用,我想直接通过方法选中一个节点如何操作,用selectAt传坐标,不多余吗?3、鼠标事件里的groups怎么没」。
|
|
484
|
+
|
|
485
|
+
- **选中回调统一**:点击、框选与 `selectFeatures()` / `deselect()` / `selectAt()` 共用同一份选中状态,实际改变选中集时都从组件级 `handleSelectPayload(payload, detail)` 发出 `onSelect` 与 `onSelectChange`;接口来源 `cause: 'api'`,原样重设同一选中集只同步镜像与读数、不重复发回调。
|
|
486
|
+
- **selectAt 与 selectFeatures 的分工**:`selectAt(clientX, clientY)` 只用于手上只有客户端坐标、需要像普通单击一样命中的场景;它走同一套 `pick()`,立即生效但不派发 `onClick` / `onDblClick`。已知节点 / 线路 id 时直接 `selectFeatures('id')` 或传引用,不必先求坐标;两套入口落到同一份选中 state,样式与读数没有区别。
|
|
487
|
+
- **鼠标分组载荷**:通道回线最终命中时,拾取结果补 `groups`(同一通道全部分组,按声明顺序,每项带 `groupIndex` / `lineIds` / `path` 与成员 / 拐点读数);`group` 仍是当前命中的那一组。`pickAt`、`hoverAt` / `onHover`、`onPointerDown` / `onPointerUp`、`onClick` / `onDblClick`、`onContextMenu` 都带这两个字段,且全部分组只在最终命中后构建,避免悬停扫描反复复制成员数组。
|
|
488
|
+
- **核心文件**:`src/gis-view/create.js`、`src/gis-view/engine.js`、`src/gis-view/types.d.ts`、`docs/steps/selftest-select.html`、`docs/manual/04-事件与回调.md`、`07-指针与要素编辑.md`、`08-选中与拐点.md`、`09-通道与多回线.md`、`16-实例方法总表.md`、`17-参数速查.md`、`18-逐方法示例.md`、`src/gis-view/README.md`、`docs/steps/README.md`、`docs/demos/api-index.js`(生成物)与本轮 aimd。
|
|
489
|
+
- **验证**:`node --check src/gis-view/create.js`、`node --check src/gis-view/engine.js`、`npx tsc --noEmit`;`selftest-select.html` **79** 条、`selftest-features.html` **672** 条、`selftest-docs.html` **134** 条、`selftest-demos.html` **365** 条,四页共 **1250** 条通过 / 0 失败;`node docs/steps/gen-api-index.mjs --check`、`npm run check:docs`(265 个实例成员 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关全部命中)、`npm run build` 与 `git diff --check` 全部通过(后者仅有 CRLF 提示)。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-26-增量修改txt统一选中回调与鼠标分组载荷)。
|
|
490
|
+
- **历史口径**:本节之前的「选中接口的回调口径」保留上一轮“接口只发 onSelectChange”的记录;本轮已统一为实际变化时同时发 `onSelect` 与 `onSelectChange`,以本节为准。
|
|
491
|
+
|
|
492
|
+
### 2026-10-26 增量(「修改.txt」:选中事件分工、通道上下文与派发顺序)
|
|
493
|
+
|
|
494
|
+
本轮仍是现有会话的继续增量,没有独立会话归档,因此不改上表的 39 条统计。需求原话来自仓库根目录最新的 `修改.txt`:「修改gis-view组件 1、onSelectChange和onSelect有必要同时存在吗,各自的意义是什么 2、为什么这两个事件里都拿不到通道的信息,group和groups都没有,隐藏这两个参数的意义是什么 3、为什么控制台顺序onSelectChange>onSelect>onClick」。
|
|
495
|
+
|
|
496
|
+
- **分工结论**:保留两个事件。`onSelect` 是本次选中操作回调(真实单击 / Ctrl / `multiSelect` 取反 / 框选 / `selectAt()` 每次成功操作都发,清空或取反取没了时载荷 `null`;`selectFeatures` / `deselect` / `focusOn({ select })` 只在集合实际变化时发),`onSelectChange` 是集合状态回调(所有来源都只在实际变化时发,带 `ids` / `count` / 类型计数 / `cause` / `action`)。
|
|
497
|
+
- **通道载荷**:两条回调都带同一份通道上下文。单通道时顶层平铺 `channelId` / `channelIndex` / `channel` / `groupId` / `groupIndex` / `group` / `groups`;多通道时只给 `channelContexts`(每项另有本次选中的 `lineIndexes` / `lineIds`)。`items[]` 里的通道回线也补 `group` / `groups`。真实单击与 `selectAt` 的当前组是命中的组;框选与按引用接口取选中集里第一条通道回线所在的组;`groups` 始终是整条通道的全部分组。
|
|
498
|
+
- **顺序修复**:旧顺序 `onSelectChange → onSelect → onClick` 已改为普通单击 `onClick → onSelect → onSelectChange`;Ctrl / `multiSelect` 取反、框选与接口选中是 `onSelect → onSelectChange`;双击模式第二下最后再补 `onDblClick`。`deferredSelection` 只延后点击路径的选中回调,选中镜像与标签仍先同步,回调内读 `getSelectionData()` 已是最新。
|
|
499
|
+
- **根因修复**:分组通道的 `channelIndex` 原来误取分组状态序号 `state.order`,现统一为通道在 `channels` 声明数组里的下标 `state.channelIndex`,覆盖拾取 / 悬停 / `describe` / `listLines` / 级联 / `getLineChannel` 六处。
|
|
500
|
+
- **核心文件**:`src/gis-view/engine.js`、`src/gis-view/create.js`、`src/gis-view/types.d.ts`、`docs/steps/selftest-select.html`、`docs/manual/04-事件与回调.md`、`07-指针与要素编辑.md`、`08-选中与拐点.md`、`09-通道与多回线.md`、`16-实例方法总表.md`、`17-参数速查.md`、`18-逐方法示例.md`、`src/gis-view/README.md`、`docs/steps/README.md`、`docs/demos/gis-view-demo/useGisViewDemo.js`、`docs/demos/api-index.js`(生成物)与本轮 aimd。
|
|
501
|
+
- **验证**:`node --check src/gis-view/engine.js`、`node --check src/gis-view/create.js`、`npx tsc --noEmit`;四页定向自测 **1254** 条通过 / 0 失败(select 83 / features 672 / docs 134 / demos 365);`npm run build` 通过;`node docs/steps/gen-api-index.mjs --check` PASS(索引最新)、`npm run check:docs` 全 PASS(265 个实例成员 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关)、`git diff --check` 通过(仅有 CRLF 提示)。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-26-增量修改txt选中事件分工通道上下文与派发顺序)。
|
|
502
|
+
|
|
503
|
+
### 2026-10-26 增量(「修改.txt」:选中载荷去重与通道索引缓存)
|
|
504
|
+
|
|
505
|
+
本轮仍是现有会话的继续增量,没有独立会话归档,因此不改上表的 39 条统计。需求原话来自仓库根目录最新的 `修改.txt`:「修改gis-view组件 1、本次修改会影响组件性能吗,比如事件参数添加group和groups,selectFeatures触发onSelect等,如果影响性能,如何优化 2、现在onSelect和onSelectChange参数都有通道信息,下面的items里面也有通道信息,是不是有些多余, 3、继续检查组件,有没有冗余代码,继续提高组件性能」。
|
|
506
|
+
|
|
507
|
+
- **性能结论**:选中事件不进入逐帧渲染路径;两条事件共享同一批 `items`、分组对象与数组引用,不深拷贝。`selectFeatures()` 只在集合实际变化时发事件,同内容、同顺序的重设会在 `selectionKeys()`、引擎刷新与 `describeSelection()` 之前直接返回;`selectAt()` 每次成功命中发 `onSelect` 是既定语义。新增开销只随本次选中的通道 / 分组数增长。
|
|
508
|
+
- **载荷去重**:单通道只摊平顶层 `channelId` / `channelIndex` / `channel` / `groupId` / `groupIndex` / `group` / `groups`,不再生成 `channelContexts`;多通道才用 `channelContexts`。`items[]` 的通道回线只保留 `channelId` / `channelIndex` / `groupId` / `groupIndex` 标量,不重复挂 `group` / `groups`。指针事件仍保留自己的 `group` / `groups`。上一节逐条补充的口径已撤回。
|
|
509
|
+
- **索引与冗余**:`resolveChannels()` 同步维护 `channelGroupStatesByIndex`,状态上记录 `groupOrdinal`;`channelSiblings()` / `channelGroupOrdinal()` 变 O(1),分组读数从 O(组数 × 通道数) 降为 O(组数)。当前组改用组序号直取,删掉 `findIndex`、`state.order` 和建通道时重复的 `channels.filter(...)`。单通道选中不再构造随后丢弃的 `lineIndexes` / `lineIds`,多通道才在 `channelContexts` 里按选中顺序补一次。
|
|
510
|
+
- **核心文件**:`src/gis-view/engine.js`、`src/gis-view/create.js`、`src/gis-view/types.d.ts`、`docs/steps/selftest-select.html`、`docs/steps/README.md`、`docs/manual/04-事件与回调.md`、`07-指针与要素编辑.md`、`09-通道与多回线.md`、`20-性能与大数据.md`、`src/gis-view/README.md` 与本轮 aimd。
|
|
511
|
+
- **验证**:`node --check src/gis-view/engine.js`、`node --check src/gis-view/create.js`、`npx tsc --noEmit`、`npm run build` 通过;五页定向自测 **1438** 条通过 / 0 失败(select 84 / features 672 / docs 134 / demos 365 / perf 183);`node docs/steps/gen-api-index.mjs --check` PASS(索引最新)、`npm run check:docs` 全 PASS(265 个实例成员 / 250 个数据字段 / 96 个 options / 43 个事件 / 17 个功能开关)、`git diff --check` 通过(仅有 CRLF 提示)。详细口径见 [AI 对话汇总的本轮增量](../AI对话汇总.md#2026-10-26-增量修改txt选中载荷去重与通道索引缓存)。
|
|
512
|
+
|
|
451
513
|
## 六、怎么自己复查
|
|
452
514
|
|
|
453
515
|
会话文件是逐行 JSON,不用整份读 —— 只挑两种行解析就够:`session_meta` 行里的 `payload.cwd` 认项目,`payload.type === 'user_message'` 行里的 `payload.message` 是用户原话:
|
package/docs/demos/LabelDemo.vue
CHANGED
|
@@ -477,8 +477,8 @@ onMounted(() => {
|
|
|
477
477
|
pushLog('labelChange', describeChange(payload))
|
|
478
478
|
syncLabelStates()
|
|
479
479
|
}],
|
|
480
|
-
//
|
|
481
|
-
['selectChange', () => syncSelection()]
|
|
480
|
+
// 选中镜像统一走 selectChange:覆盖点击与接口来源,且重复设同一份选中集不会重复通知
|
|
481
|
+
['selectChange', () => syncSelection()]
|
|
482
482
|
].map(([name, handler]) => view.on(name, handler))
|
|
483
483
|
window.addEventListener('keydown', onKeyDown)
|
|
484
484
|
window.addEventListener('pointerdown', onGlobalPointerDown)
|
package/docs/demos/StyleDemo.vue
CHANGED
|
@@ -86,7 +86,7 @@ const buildOptions = () => ({
|
|
|
86
86
|
syncRules()
|
|
87
87
|
},
|
|
88
88
|
/**
|
|
89
|
-
* 读数接 onSelectChange 而不是 onSelect:前者对「点选、框选、API
|
|
89
|
+
* 读数接 onSelectChange 而不是 onSelect:前者对「点选、框选、API selectFeatures()」都会发,
|
|
90
90
|
* 后者只代表画布上的那一次点击 —— 用接口选中时读数也不会停在「未选中」。
|
|
91
91
|
* 选中高亮的颜色 / 尺寸写在 pointSelectStyle / lineSelectStyle 里,这里只让面板知道选中集变了。
|
|
92
92
|
*/
|
package/docs/demos/api-index.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* 源码或文档改过之后重跑一遍;`node docs/steps/check-doc-coverage.mjs` 会对账。
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
/** { members:
|
|
11
|
-
export const API_SUMMARY = {"members":
|
|
10
|
+
/** { members: 265, methods: 260, properties: 5, options: 96, sections: 16 } */
|
|
11
|
+
export const API_SUMMARY = {"members":265,"methods":260,"properties":5,"options":96,"sections":16}
|
|
12
12
|
|
|
13
13
|
/** 实例成员,按 docs/GisView.md「参数速查」的分组排 */
|
|
14
14
|
export const API_SECTIONS = [
|
|
@@ -98,8 +98,9 @@ export const API_SECTIONS = [
|
|
|
98
98
|
{ name: "createGeoMapper", kind: "method", params: "options?: GisViewGeoMapperOptions 映射选项(lngKey / latKey / xKey / yKey / fit…)", returns: "GisViewGeoMapper | null", doc: "建一个「数据坐标 → GeoJSON 坐标」的映射器:mode: 'lngLat' | 'fit' | 'scale'、scale(节点与 geojson 的大小比例)、scaleX / scaleY / offsetX / offsetY / center / bounds / data / padding / target,返回 map / unmap / mapPoint / mapLine / mapChannel / mapData 与最终的比例偏移;没有 GeoJSON 背景时是 null", examples: [{"group":"坐标、拾取与读数","code":"// createGeoMapper(options?) / mapDataToGeoJson(data, options?):把另一套坐标系的数据搬到画出来的底图上\nconst mapper = view.createGeoMapper({ mode: 'fit', padding: 0.08, data })\nconst mappedPoints = view.getData().points.map(mapper.mapPoint)\nconst mapped = view.mapDataToGeoJson({ points, lines, channels }, { mode: 'fit' })\nview.updateData(mapped.points, mapped.lines)\n","from":"header"}] },
|
|
99
99
|
{ name: "mapDataToGeoJson", kind: "method", params: "data: { points?, lines?, channels? } 要搬的数据;options?: GisViewGeoMapperOptions 同 createGeoMapper", returns: "GisViewPoint[]; lines?: GisViewLine[]; channels?: GisViewChannel[] }>(data: T, options?: GisViewGeoMapperOptions): T | null", doc: "createGeoMapper(options).mapData(data) 的快捷写法:把 { points, lines, channels } 整份搬到 GeoJSON 坐标,原数据不动;没有 GeoJSON 背景时是 null", examples: [{"group":"坐标、拾取与读数","code":"// createGeoMapper(options?) / mapDataToGeoJson(data, options?):把另一套坐标系的数据搬到画出来的底图上\nconst mapper = view.createGeoMapper({ mode: 'fit', padding: 0.08, data })\nconst mappedPoints = view.getData().points.map(mapper.mapPoint)\nconst mapped = view.mapDataToGeoJson({ points, lines, channels }, { mode: 'fit' })\nview.updateData(mapped.points, mapped.lines)\n","from":"header"}] },
|
|
100
100
|
{ name: "getPointer", kind: "method", params: "无", returns: "GisViewPointerState", doc: "当前光标状态 { inside, screen, world, lngLat }(onPointer 回调的同一份数据)", examples: [{"group":"坐标、拾取与读数","code":"// getPointer():光标位置读数 { inside, screen, world, lngLat }\nconst pointer = view.getPointer()\n","from":"header"}] },
|
|
101
|
-
{ name: "pick", kind: "method", params: "x / y 画布 CSS 像素", returns: "GisViewPickResult | null", doc: "拾取指定画布位置上的要素(clickable: false 的要素不会返回)", examples: [{"group":"坐标、拾取与读数","code":"//(pick / getContextAt / nearestPointsAt 这些吃画布像素的方法先用这一对转;自动处理 canvas rect 与宿主缩放)\nconst [sx, sy] = view.clientToScreen(event.clientX, event.clientY)\nconst [fixedX, fixedY] = view.screenToClient(320, 200) // 摆 position: fixed 的浮层 / 菜单\n","from":"header"},{"group":"坐标、拾取与读数","code":"// pick(x, y) / pickAt(clientX, clientY):按画布像素 / 客户端坐标拾取\nconst hit = view.pick(320, 200)\nconst hitAt = view.pickAt(event.clientX, event.clientY)\n","from":"header"}] },
|
|
102
|
-
{ name: "pickAt", kind: "method", params: "clientX / clientY 浏览器客户端坐标(PointerEvent
|
|
101
|
+
{ name: "pick", kind: "method", params: "x / y 画布 CSS 像素", returns: "GisViewPickResult | null", doc: "拾取指定画布位置上的要素(clickable: false 的要素不会返回)", examples: [{"group":"坐标、拾取与读数","code":"//(pick / getContextAt / nearestPointsAt 这些吃画布像素的方法先用这一对转;自动处理 canvas rect 与宿主缩放)\nconst [sx, sy] = view.clientToScreen(event.clientX, event.clientY)\nconst [fixedX, fixedY] = view.screenToClient(320, 200) // 摆 position: fixed 的浮层 / 菜单\n","from":"header"},{"group":"坐标、拾取与读数","code":"// pick(x, y) / pickAt(clientX, clientY):按画布像素 / 客户端坐标拾取\nconst hit = view.pick(320, 200)\nconst hitAt = view.pickAt(event.clientX, event.clientY)\nhitAt?.groups // 命中通道回线:同一通道的全部分组;hitAt.group 是当前这一组\n","from":"header"}] },
|
|
102
|
+
{ name: "pickAt", kind: "method", params: "clientX / clientY 浏览器客户端坐标(PointerEvent 原样给);命中通道回线时返回的 group 是当前组、groups 是整条通道的全部分组", returns: "GisViewPickAtResult | null", doc: "按浏览器客户端坐标拾取(就是鼠标事件里的 clientX / clientY):与指针事件载荷同一份结果(type / index / item / distance / screen / coordinate 与通道字段),另加 target('point' / 'line' / 'channel')与 lngLat;命中通道回线时 group 是当前组、groups 是整条通道的全部分组;没命中返回 null。只读,不改选中也不动光标", examples: [{"group":"坐标、拾取与读数","code":"// pick(x, y) / pickAt(clientX, clientY):按画布像素 / 客户端坐标拾取\nconst hit = view.pick(320, 200)\nconst hitAt = view.pickAt(event.clientX, event.clientY)\nhitAt?.groups // 命中通道回线:同一通道的全部分组;hitAt.group 是当前这一组\n","from":"header"}] },
|
|
103
|
+
{ name: "selectAt", kind: "method", params: "clientX / clientY 浏览器客户端坐标;按普通单击的命中与通道摊开规则立即选中,空白 / 聚合圆返回 null、不改选中,不派发 onClick / onDblClick。每次成功命中都发 onSelect,选中集实际变化时再发 onSelectChange(cause: 'api',顺序 onSelect → onSelectChange);通道回线载荷带当前 group / 完整 groups,多通道看 channelContexts。已知 id 时优先 selectFeatures", returns: "GisViewSelectPayload | null", doc: "只有客户端坐标时用它像普通单击一样立即选中命中要素:节点 / 线路直接选中,通道回线按 channelSelectMode 摊开;空白或聚合圆返回 null 且不改选中。不等待 selectTrigger: 'dblClick',也不派发 onClick / onDblClick;每次成功命中都发 onSelect,选中集实际变化时再发 onSelectChange,顺序 onSelect → onSelectChange(cause: 'api')。选中通道回线时载荷带当前 group / 完整 groups,多通道看 channelContexts。已知节点 / 线路 id 时直接用 selectFeatures,见「按坐标单击选中(selectAt)」", examples: [{"group":"选中、复制与合并","code":"// selectAt(clientX, clientY):每次命中发 onSelect,集合变化时再发 onSelectChange(不动指针、不派发 onClick);已知 id 直接用 selectFeatures\nview.selectAt(event.clientX, event.clientY) // 节点 / 线路命中即选中;空白返回 null\nview.updateOptions({ channelSelectMode: 'channel' })\nview.selectAt(event.clientX, event.clientY) // 命中任一回线 = 选中整条通道\n","from":"header"}] },
|
|
103
104
|
{ name: "hoverAt", kind: "method", params: "clientX / clientY 客户端坐标", returns: "GisViewHoverPayload | null", doc: "程序化悬停:hoverAt 让指针「停」到某个客户端坐标上(悬停高亮、光标与 onHover 一起更新,返回与 onHover 载荷同一份读数,空白处 null;不走悬停阈值,也不用先订阅事件)、clearHover() 撤掉并补发一条 onHover(null)、getHover() 随时读当前这一份 —— 外部列表 / 表格 hover 到某一行时联动高亮图上的要素用它", examples: [{"group":"坐标、拾取与读数","code":"// hoverAt(clientX, clientY) / clearHover() / getHover():程序化悬停 / 撤掉 / 读当前那一份\nview.hoverAt(event.clientX, event.clientY)\nview.clearHover()\nconst hover = view.getHover()\n","from":"header"}] },
|
|
104
105
|
{ name: "clearHover", kind: "method", params: "无", returns: "null", doc: "程序化悬停:hoverAt 让指针「停」到某个客户端坐标上(悬停高亮、光标与 onHover 一起更新,返回与 onHover 载荷同一份读数,空白处 null;不走悬停阈值,也不用先订阅事件)、clearHover() 撤掉并补发一条 onHover(null)、getHover() 随时读当前这一份 —— 外部列表 / 表格 hover 到某一行时联动高亮图上的要素用它", examples: [{"group":"坐标、拾取与读数","code":"// hoverAt(clientX, clientY) / clearHover() / getHover():程序化悬停 / 撤掉 / 读当前那一份\nview.hoverAt(event.clientX, event.clientY)\nview.clearHover()\nconst hover = view.getHover()\n","from":"header"}] },
|
|
105
106
|
{ name: "getHover", kind: "method", params: "无", returns: "GisViewHoverPayload | null", doc: "程序化悬停:hoverAt 让指针「停」到某个客户端坐标上(悬停高亮、光标与 onHover 一起更新,返回与 onHover 载荷同一份读数,空白处 null;不走悬停阈值,也不用先订阅事件)、clearHover() 撤掉并补发一条 onHover(null)、getHover() 随时读当前这一份 —— 外部列表 / 表格 hover 到某一行时联动高亮图上的要素用它", examples: [{"group":"坐标、拾取与读数","code":"// hoverAt(clientX, clientY) / clearHover() / getHover():程序化悬停 / 撤掉 / 读当前那一份\nview.hoverAt(event.clientX, event.clientY)\nview.clearHover()\nconst hover = view.getHover()\n","from":"header"}] },
|
|
@@ -137,14 +138,14 @@ export const API_SECTIONS = [
|
|
|
137
138
|
{
|
|
138
139
|
title: "选中、复制与合并",
|
|
139
140
|
items: [
|
|
140
|
-
{ name: "selectFeatures", kind: "method", params: "refs: GisViewSelectionRefs 要选中的东西:节点 / 线路 id、id 数组、{ type, index }、通道写法({ type: 'channel', channelId | channelIndex },可再给 groupIds / lineIds / lineIndexes 取子集)、分组写法({ type: 'group', channelId?, groupId },groupId 全局唯一时可省略通道)、拾取载荷 / 搜索命中,传 null / 空数组等于清空一份新的选中集。认不出来的条目逐条跳过;options?: GisViewSelectOptions 只有 mode:'replace' 缺省换一份、'add' 追加、'toggle' 在就取消 / 不在就选上、'remove' 去掉", returns: "this
|
|
141
|
+
{ name: "selectFeatures", kind: "method", params: "refs: GisViewSelectionRefs 要选中的东西:节点 / 线路 id、id 数组、{ type, index }、通道写法({ type: 'channel', channelId | channelIndex },可再给 groupIds / lineIds / lineIndexes 取子集)、分组写法({ type: 'group', channelId?, groupId },groupId 全局唯一时可省略通道)、拾取载荷 / 搜索命中,传 null / 空数组等于清空一份新的选中集。认不出来的条目逐条跳过;options?: GisViewSelectOptions 只有 mode:'replace' 缺省换一份、'add' 追加、'toggle' 在就取消 / 不在就选上、'remove' 去掉", returns: "this(选中真的变了才按 onSelect → onSelectChange 发,cause 为 api;载荷带通道上下文)", doc: "接口选中(换一份选中集;selectFeatures(null) / 空数组就是清空):refs 认节点 / 线路 id、id 数组、{ type, index }、通道写法({ type: 'channel', channelId } / { channelId, groupId } / { channelId, lineIds })、分组写法({ type: 'group', channelId?, groupId },全局唯一 groupId 可省略通道)以及拾取载荷与搜索命中;options.mode 给 'replace'(缺省,换一份)/ 'add' / 'toggle'(在就取消、不在就选上)/ 'remove'。会同步选中样式与读数;选中集实际变化时按 onSelect → onSelectChange 派发(cause: 'api'),载荷带同一份通道上下文(单通道摊平,多通道看 channelContexts),不发 onClick / onDblClick,见「接口选中(selectFeatures)与读回选中」", examples: [{"group":"选中、复制与合并","code":"// selectFeatures(refs, options?):接口选中(与点击选中走同一份 state;实际变化时按 onSelect → onSelectChange 发,载荷带通道上下文)\nview.selectFeatures('a') // 选中一个\nview.selectFeatures(['a', 'b']) // 一批\nview.selectFeatures('a', { mode: 'add' }) // mode:replace(缺省)/ add / toggle / remove\nview.selectFeatures([{ type: 'line', index: 0 }], { mode: 'toggle' })\nview.selectFeatures({ type: 'channel', channelId: 'c1' }) // 整条通道的全部回线\nview.selectFeatures({ type: 'group', channelId: 'c1', groupId: 'c1::2' })\nview.selectFeatures({ type: 'group', groupId: 'global-group' }) // groupId 全局唯一时可省略通道\nview.selectFeatures(null) // 清空(空数组同义)\n","from":"header"}] },
|
|
141
142
|
{ name: "selectWaypoint", kind: "method", params: "lineRef 线路 id、lines 下标或 { lineIndex, pathIndex } / { lineId, pathIndex } 对象;pathIndex?: number 必须是 getWaypoints() 给出的可编辑中间拐点下标(首尾端点不算,通常直接从读数里取);options?: GisViewSelectOptions 的 mode 决定所在线路怎么并进当前选中集(缺省 replace)。有效拐点会同时选中线路;线路不存在 / 下标非法 / 拐点不可见时只清拐点选中,不猜位置;传 null 也只清拐点,不改要素选中集", returns: "this", doc: "代码选中一个拐点:selectWaypoint('line-1', 2) / { lineIndex, pathIndex } / { lineId, pathIndex },并同时选中所在线路;有效下标从 getWaypoints() 取。传 null 只取消拐点选中、不改要素选中集,见「代码选中拐点(selectWaypoint)」", examples: [{"group":"选中、复制与合并","code":"// selectWaypoint(lineRef, pathIndex? / { lineIndex | lineId, pathIndex }, options?):选中拐点并带选线路\nview.selectWaypoint('l1', 2) // pathIndex 从 getWaypoints() 取\nview.selectWaypoint({ lineIndex: 0, pathIndex: 1 }, { mode: 'add' })\nview.selectWaypoint({ lineId: 'l1', pathIndex: 2 })\nview.selectWaypoint(null) // 只取消拐点选中,不改要素选中集\n","from":"header"}] },
|
|
142
|
-
{ name: "deselect", kind: "method", params: "refs?: GisViewSelectionRefs 要取消的东西(写法与 selectFeatures 一致:节点 / 通道 / 线路 / 混合一批);不传 / null 等于取消全部(= selectFeatures(null)),空数组是「没有目标」什么都不做", returns: "this", doc: "取消选中:写法与 selectFeatures 完全一样,把这些从当前选中集里去掉、其余选中原样留着;不传 / null 等于取消全部(也就是 selectFeatures(null)
|
|
143
|
+
{ name: "deselect", kind: "method", params: "refs?: GisViewSelectionRefs 要取消的东西(写法与 selectFeatures 一致:节点 / 通道 / 线路 / 混合一批);不传 / null 等于取消全部(= selectFeatures(null)),空数组是「没有目标」什么都不做", returns: "this(选中真的变了才按 onSelect → onSelectChange 发,cause 为 api;清空时 onSelect 载荷为 null)", doc: "取消选中:写法与 selectFeatures 完全一样,把这些从当前选中集里去掉、其余选中原样留着;不传 / null 等于取消全部(也就是 selectFeatures(null)),空数组是「没有目标」什么都不做。改变选中集时按 onSelect → onSelectChange 派发(cause: 'api';清空时 onSelect 载荷为 null),见「取消选中(deselect / selectFeatures(null))」", examples: [{"group":"选中、复制与合并","code":"// deselect(refs?):取消选中(写法与 selectFeatures 一致;不传 / null 全清,空数组什么都不做)\nview.deselect('a')\nview.deselect(['a', 'b'])\nview.deselect()\n","from":"header"}] },
|
|
143
144
|
{ name: "getSelections", kind: "method", params: "无", returns: "GisViewPickResult[]", doc: "读回选中结果 [{ type, index, item, … }](按选中顺序):要 id 列表 / 个数 / 包围盒看 getSelectionData()", examples: [{"group":"选中、复制与合并","code":"// getSelections() / getSelectionData() / isSelected(ref):读回选中\nconst picks = view.getSelections()\nconst selection = view.getSelectionData() // { ids, count, points, lines, channels, bounds, … }\nconst selected = view.isSelected('a')\n","from":"header"}] },
|
|
144
145
|
{ name: "isSelected", kind: "method", params: "ref: GisViewFeatureRef | GisViewFeatureKey | GisViewSelectionRefObject 要素定位(id / 下标 / { id } / { index } / { type, index } / { item })", returns: "boolean", doc: "这个要素在不在当前选中集里:isSelected('node-0')(id)/ isSelected({ type: 'line', index: 12 })(也可以只写下标,按 id 认不出来时当下标),返回 true / false。面板上高亮「当前这一行」时不必自己比对 getSelections();选中集变化时缓存一份键集合(见「接口选中」),十万级选中下这一问也是常数级", examples: [{"group":"选中、复制与合并","code":"// getSelections() / getSelectionData() / isSelected(ref):读回选中\nconst picks = view.getSelections()\nconst selection = view.getSelectionData() // { ids, count, points, lines, channels, bounds, … }\nconst selected = view.isSelected('a')\n","from":"header"}] },
|
|
145
146
|
{ name: "getSelectionData", kind: "method", params: "无", returns: "GisViewSelectionData:{ ids, count, pointCount, lineCount, channelCount, points, lines, channels, items, pointIndexes, lineIndexes, bounds }(bounds 是世界包围盒,空选中时 null)", doc: "选中集一次取全:读数(ids / count / pointCount / lineCount / channelCount)加要素本身(points / lines / channels(按通道去重,与 getData() 同一批对象)),另有 items(与 getSelections() 同一份)、pointIndexes / lineIndexes 与 bounds(世界包围盒,空选中时 null),见「接口选中(selectFeatures)与读回选中」", examples: [{"group":"选中、复制与合并","code":"// getSelections() / getSelectionData() / isSelected(ref):读回选中\nconst picks = view.getSelections()\nconst selection = view.getSelectionData() // { ids, count, points, lines, channels, bounds, … }\nconst selected = view.isSelected('a')\n","from":"header"}] },
|
|
146
147
|
{ name: "getCascadeHighlight", kind: "method", params: "无", returns: "GisViewCascadeHighlightInfo | null:当前点击级联高亮的来源、范围与节点 / 线路读数 { origin, scope, points, lines, pointIndexes, lineIndexes },不改变选中集", doc: "当前点击级联高亮的读数:{ origin, scope, points, lines, pointIndexes, lineIndexes };没有高亮或 cascadeHighlight 关着时返回 null。它只读、不改选中集,见「点击级联高亮」", examples: [{"group":"选中、复制与合并","code":"// getCascadeHighlight():读点击级联高亮(与选中集分开;没有高亮时为 null)\nconst cascade = view.getCascadeHighlight() // { origin, scope, points, lines, pointIndexes, lineIndexes }\nview.updateOptions({\n cascadeHighlight: {\n scope: 'points',\n triggerOnClick: true,\n triggerOnMultiSelect: false,\n triggerOnBoxSelect: true,\n clearOnEmptyClick: true\n }\n})\nview.on('cascadeHighlight', payload => console.log(payload?.pointIndexes, payload?.lineIndexes))\n","from":"header"}] },
|
|
147
|
-
{ name: "selectInBox", kind: "method", params: "box: GisViewRect 画布 CSS 像素矩形 { x, y, width, height }(与手动框选同一套坐标);options?: GisViewSelectInBoxOptions:selectionKinds 临时覆盖这一次保留哪几类('point' / 'line' / 'channel'、数组、'all' / true / false / null,不写沿用全局 selectionKinds),originalEvent 原样带进 onSelect;第二段也兼容旧的 Event 写法。空框不会选中任何要素", returns: "this
|
|
148
|
+
{ name: "selectInBox", kind: "method", params: "box: GisViewRect 画布 CSS 像素矩形 { x, y, width, height }(与手动框选同一套坐标);options?: GisViewSelectInBoxOptions:selectionKinds 临时覆盖这一次保留哪几类('point' / 'line' / 'channel'、数组、'all' / true / false / null,不写沿用全局 selectionKinds),originalEvent 原样带进 onSelect;第二段也兼容旧的 Event 写法。空框不会选中任何要素", returns: "this(每次框选都发 onSelect,空框为 null;集合变化时再发 onSelectChange,顺序 onSelect → onSelectChange,cause 为 boxSelect)", doc: "按画布 CSS 像素矩形框选,等价于 Shift + 拖动(跟随 shortcuts.boxSelect);options.selectionKinds 可只覆盖这一次的节点 / 线路 / 通道类型过滤。每次框选操作都发 onSelect(空框的载荷为 null),选中集实际变化时再发 onSelectChange,顺序 onSelect → onSelectChange(cause: 'boxSelect');通道回线的分组字段与鼠标框选同一份", examples: [{"group":"选中、复制与合并","code":"// selectInBox(box, options?):用矩形框选(画布 CSS 像素,与手动框选同一套判定)\nview.selectInBox({ x: 40, y: 40, width: 320, height: 200 })\nview.selectInBox({ x: 40, y: 40, width: 320, height: 200 }, { selectionKinds: ['line', 'channel'] })\n","from":"header"}] },
|
|
148
149
|
{ name: "beginCopyPoint", kind: "method", params: "options: GisViewCopyStartOptions:id / index / item 三选一给来源,都不给就进入「下一次点选节点」模式;coordinate / screen 是落点(缺省按 copy.offset);follow 让预览跟指针;autoCommit 覆盖 copy.autoCommit;commit: true 出预览即落地;via / originalEvent 原样带回。必须配置 copy(enabled 不为 false),否则返回 null。预览节点插在 points 末尾且不带 id,不会把绑定源 id 的线路 / 通道带过去", returns: "GisViewPointCopyPayload | null:phase: 'start' 的预览载荷;来源认不出来时返回 null", doc: "开始复制一个节点:给 id / index 直接出预览(commit: true 出预览即落地,follow: true 跟随鼠标,autoCommit: false 停在预览态),不给来源就是「先点按钮再选节点」模式,见「节点复制」", examples: [{"group":"选中、复制与合并","code":"// beginCopyPoint(options) / getPointCopy() / updateCopyPoint(patch) / commitPointCopy() / cancelPointCopy()\nview.updateOptions({ copy: { enabled: true, autoCommit: false } }) // API 复制入口要先开 copy 配置\nview.beginCopyPoint({ id: 'a', coordinate: [40, 30] }) // 出预览并钉在世界坐标 [40, 30]\nview.beginCopyPoint({ id: 'a', follow: true }) // 预览跟着指针走(autoCommit 缺省停住)\nview.beginCopyPoint() // 先点按钮再选节点(点中下一个节点当来源)\nview.updateCopyPoint({ name: '新节点' }) // 字段级改预览节点(落点仍由 coordinate / 指针决定)\nconst copyEnd = view.commitPointCopy() // 落地:返回 end 载荷;没有预览时为 null\nview.cancelPointCopy() // 取消:预览撤掉,数据与历史不动\nconst copyState = view.getPointCopy() // 当前预览 / 选点态(没有就是 null)\n","from":"header"}] },
|
|
149
150
|
{ name: "commitPointCopy", kind: "method", params: "无:把当前复制预览落地,先发 commit、落地后发 end;commit 阶段载荷里的 cancel() 可以拦住这次复制", returns: "GisViewPointCopyPayload | null:成功的 end 载荷;没有预览或已被取消时为 null", doc: "落地 / 取消预览中的复制(返回 end / cancel 载荷)", examples: [{"group":"选中、复制与合并","code":"// beginCopyPoint(options) / getPointCopy() / updateCopyPoint(patch) / commitPointCopy() / cancelPointCopy()\nview.updateOptions({ copy: { enabled: true, autoCommit: false } }) // API 复制入口要先开 copy 配置\nview.beginCopyPoint({ id: 'a', coordinate: [40, 30] }) // 出预览并钉在世界坐标 [40, 30]\nview.beginCopyPoint({ id: 'a', follow: true }) // 预览跟着指针走(autoCommit 缺省停住)\nview.beginCopyPoint() // 先点按钮再选节点(点中下一个节点当来源)\nview.updateCopyPoint({ name: '新节点' }) // 字段级改预览节点(落点仍由 coordinate / 指针决定)\nconst copyEnd = view.commitPointCopy() // 落地:返回 end 载荷;没有预览时为 null\nview.cancelPointCopy() // 取消:预览撤掉,数据与历史不动\nconst copyState = view.getPointCopy() // 当前预览 / 选点态(没有就是 null)\n","from":"header"}] },
|
|
150
151
|
{ name: "cancelPointCopy", kind: "method", params: "无:撤掉预览并补一条 cancel,数据与历史不动", returns: "GisViewPointCopyPayload | null:取消载荷;没有预览时为 null", doc: "落地 / 取消预览中的复制(返回 end / cancel 载荷)", examples: [{"group":"选中、复制与合并","code":"// beginCopyPoint(options) / getPointCopy() / updateCopyPoint(patch) / commitPointCopy() / cancelPointCopy()\nview.updateOptions({ copy: { enabled: true, autoCommit: false } }) // API 复制入口要先开 copy 配置\nview.beginCopyPoint({ id: 'a', coordinate: [40, 30] }) // 出预览并钉在世界坐标 [40, 30]\nview.beginCopyPoint({ id: 'a', follow: true }) // 预览跟着指针走(autoCommit 缺省停住)\nview.beginCopyPoint() // 先点按钮再选节点(点中下一个节点当来源)\nview.updateCopyPoint({ name: '新节点' }) // 字段级改预览节点(落点仍由 coordinate / 指针决定)\nconst copyEnd = view.commitPointCopy() // 落地:返回 end 载荷;没有预览时为 null\nview.cancelPointCopy() // 取消:预览撤掉,数据与历史不动\nconst copyState = view.getPointCopy() // 当前预览 / 选点态(没有就是 null)\n","from":"header"}] },
|
|
@@ -582,7 +582,7 @@ export const useGisViewDemo = () => {
|
|
|
582
582
|
}
|
|
583
583
|
/**
|
|
584
584
|
* onSelectChange:只在选中集真的变了时发(接口选中也算),cause 说明这次是怎么选上的。
|
|
585
|
-
* 选中镜像挂在这一条上而不是 onSelect:引擎交互 / 接口
|
|
585
|
+
* 选中镜像挂在这一条上而不是 onSelect:引擎交互 / 接口 selectFeatures() / 框选接口 / 数据变更清空
|
|
586
586
|
* 都会经过它,「以谁为主」的下拉才不会漏掉接口选中那一路。
|
|
587
587
|
*/
|
|
588
588
|
const handleSelectChange = payload => {
|
|
@@ -2789,7 +2789,7 @@ export const useGisViewDemo = () => {
|
|
|
2789
2789
|
}
|
|
2790
2790
|
}
|
|
2791
2791
|
const handleSelect = (payload) => {
|
|
2792
|
-
// 选中镜像不在这里刷新:create.js 先发
|
|
2792
|
+
// 选中镜像不在这里刷新:create.js 先发 onSelect 再发 onSelectChange,上面那条已经同步过了
|
|
2793
2793
|
if (!payload) {
|
|
2794
2794
|
return
|
|
2795
2795
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
| 字段 | 载荷 | 说明 |
|
|
8
8
|
| --- | --- | --- |
|
|
9
9
|
| `onReady` | `{ canvas, gl }` | WebGL2 上下文与缓冲区就绪 |
|
|
10
|
-
| `onSelect` | `GisViewSelectPayload \| null` |
|
|
10
|
+
| `onSelect` | `GisViewSelectPayload \| null` | 选中操作回调:回答「这一下选了什么」。真实单击 / Ctrl / `multiSelect` 取反 / 框选 / `selectAt()` 每次成功操作都发(清空与「取反取没了」的载荷是 `null`);`selectFeatures()` / `deselect()` / `focusOn({ select })` 等按引用接口只在选中集实际变化时发。载荷带 `items` / `box` / `originalEvent` / `mode`;单通道时顶层还有 `channelId` / `channelIndex` / `channel` / `groupId` / `groupIndex` / `group` / `groups`,多通道看 `channelContexts`,`items[]` 里的回线只带 `channelId` / `channelIndex` / `groupId` / `groupIndex` 标量归属,不重复挂 `group` / `groups` |
|
|
11
11
|
| `onClick` | `GisViewClickPayload \| null` | 单击要素或空白处(空白处为 `null`):`type` / `item` / `index` / `screen` / `coordinate` / `button` / `selection` / `originalEvent` 之外还有 `action`(`type` 是 `select` / `toggleSelect` / `clearSelection` / `click`,`double` 说明这一下是不是双击里的第二下,`press` / `duration` / `longPress` 说明这一次按下想做什么、按了多久、算不算长按),见「指针事件」。`selectTrigger: 'dblClick'` 时第一下只发 `action.type: 'click'`,第二下才应用选中并带 `double: true` |
|
|
12
12
|
| `onClusterClick` | `GisViewClusterClickPayload` | 点中多成员聚合圆:带 `id` / `count` / `pointIndexes` / `pointIds` / `bounds` / `radius` / `coordinate` / `screen` / `selection` / `action`(`action.type` 恒为 `clusterClick`、`action.target` 为 `cluster`)。这一条**不会同时发 `onClick`**,也不会改动选中集;聚合圆内部的原始节点不参与普通点击 |
|
|
13
13
|
| `onDblClick` | `GisViewClickPayload \| null` | 双击要素或空白处(320ms / 6px 内连续两次单击):`action.type` 是 `dblClick`、`action.double` 为 `true`。普通双击在两种 `selectTrigger` 下都会于第二下派发;`dblClick` 模式下选中 / 清空 / 多选取反也在这一下应用,`click` 模式下第一下已经应用过。`click` 模式的 Ctrl / `multiSelect` 取反快捷路保持原口径,不额外发 `onClick` / `onDblClick` |
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
| `onViewport` | `GisViewViewport` | 视口尺寸 / 显示比例变化(画布按新尺寸重铺之后才发):`{ cssWidth, cssHeight, pixelRatio, displayScale }`,自建面板与小图按它跟着调整 |
|
|
38
38
|
| `onStats` | `GisViewEngineStats` | 渲染统计(点数、线数、线路批次真正铺的段数 `lineInstances`、符号数、绘制次数、`fps` / `idle` / 帧耗时、拾取耗时 `pickMs`、密度场读数 `heatDensity`,以及这一帧的光栅与线段路径 `antialias` / `software` / `thinLines`),按 `statsInterval` 节流(默认 250ms 一次)。静止画面按需渲染,这时 `idle` 为 `true`、`fps` 为 `0`,`frameMs` 是最近一帧的耗时;首帧一定会报一次(面板打开就有读数,不会一直空着) |
|
|
39
39
|
| `onDataChange` | `GisViewDataChangePayload` | 数据变更的统一出口:调用接口改数据、拖拽 / 复制 / 合并落地、拐点增删、通道新增 / 移除 / 分组都会发,载荷带动作 `type`、数据修订号 `dataVersion`、最新数据与条数,见「数据变更与其它事件」 |
|
|
40
|
-
| `onSelectChange` | `GisViewSelectChangePayload` |
|
|
40
|
+
| `onSelectChange` | `GisViewSelectChangePayload` | 选中集变化:只在选中集真的变了时发一条(框选过程中的重复同步与数据补发都不发),点击与 `selectFeatures` / `deselect` / `selectAt` 等入口都走它;载荷带 `items` / `ids` / `count` / 各类型条数、来源 `cause`、`action` 与同一份通道上下文;顺序固定排在 `onSelect` 之后 |
|
|
41
41
|
| `onShortcut` | `GisViewShortcutPayload` | 快捷键命中:`action`(`cancel` / `copy` / `paste` / `remove` / `fitView` / `undo` / `redo`)、`key` 与 `handled`(组件有没有接住,`false` 时可以接着做自己的处理 —— 没得撤销 / 重做时也是 `false`) |
|
|
42
42
|
| `onRender` | `GisViewRenderPayload` | 节流过的帧回调:`onStats` 的读数 + `frame` / `interval` / `timestamp` 与当前 `camera`,间隔见 `renderEmitInterval` |
|
|
43
43
|
| `onDataRendered` | `GisViewDataRenderedPayload` | 数据变更之后的第一帧画完(连着几次变更合并成一帧一条):载荷带那一帧的读数、这次的动作 `type`、合并的笔数 `changes` 与各列条数 `counts` —— 切场景后收 loading 用它最稳,见「动态换数据与加载完成」 |
|
|
@@ -85,16 +85,44 @@ const view = createGisView('#map', {
|
|
|
85
85
|
| `ok` / `reason` | 这一次调用成没成(`addPoints` / `addLines` / `removePoints` 这类批量接口会带上),`reason` 说明没成的原因 |
|
|
86
86
|
| 动作专属字段 | 拖拽带 `movedPoints` / `movedLines`,复制带 `item` / `source` / `revert()`(`copyPoints` / 整组粘贴另有 `sources` / `items` / `indexes` / `lines` / `channels` / `count`),合并带 `source` / `target` / `removedLines` / `mergedChannels`,拐点带 `lineIndex` / `pathIndex` / `phase`,新增带 `lineIds` / `lineIndex` / `channelId` / `groupId`(`addPoints` / `addLines` 另有 `indexes` / `items` / `position`:新要素在数组里的位置与加进去的那几条,`addChannelGroups` 另有 `results` / `groupIds` / `items`),删除带 `indexes` / `item` / `removedLineIds`,分组带 `index` / `groups` / `action`(细分动作,与 `onChannelGroupChange` 同一份);批量补丁(`patchPoints` / `patchLines`)的 `updatePoints` / `updateLines` 带 `indexes` / `items` / `count` / `skipped`,`removeSelected` 带 `pointIds` / `lineIds` / `pointIndexes` / `lineIndexes` / `removedChannels`,`filterRemove` 带 `mode: 'remove'` / `pointIndexes` / `removedPoints` / `removedLineIndexes` / `removedLineItems` / `lineIds` / `count` / `removedLines` / `removedChannels`(`points` / `lines` / `channels` 仍是删除后的最新数据) |
|
|
87
87
|
|
|
88
|
-
`
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
`onSelect` 与 `onSelectChange` 监听的是**同一份选中集**,不存在「按引用选中不算选中」这回事:点击、
|
|
89
|
+
`selectFeatures()` / `deselect()` / `selectAt()` / `focusOn({ select })`、框选与键盘清空改的都是它。
|
|
90
|
+
两者不是二选一:`onSelect` 回答「这一下选了什么」,适合跟一次具体操作;`onSelectChange` 回答「选中集
|
|
91
|
+
变了什么」,只在集合真的变化时发,适合统一同步面板 / URL / 外部状态。
|
|
92
|
+
|
|
93
|
+
- `onSelect`:真实单击、Ctrl / `multiSelect` 取反、框选(含 `selectInBox()`)与 `selectAt()` 每次成功操作都发
|
|
94
|
+
—— 即使结果和上一份选中集相同也发;点空白 / 框选空框 / 取反取没了时载荷是 `null`。按引用改选中集的
|
|
95
|
+
`selectFeatures()` / `deselect()` / `focusOn({ select })` 只在选中集实际变化时发。
|
|
96
|
+
- `onSelectChange`:覆盖所有来源,**只有选中集真的变了才发一条**;载荷另带 `ids` / `count`、
|
|
97
|
+
`points` / `lines` / `channels`(后三项是条数)与来源 `cause`、`action`。要同步面板又不想处理重复通知,订阅它。
|
|
98
|
+
|
|
99
|
+
派发顺序固定(`onSelect` 总在 `onSelectChange` 前面,事件总线里的 `select` / `selectChange` 同序;
|
|
100
|
+
下表里的 `onSelectChange` 只在实际改变选中集时出现):
|
|
101
|
+
|
|
102
|
+
| 这一下怎么选 | 实际顺序 |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| 普通单击命中 / 点空白 | `onClick → onSelect → onSelectChange`(末项有变化时;点空白时选中已清空,`onSelect` 载荷为 `null`) |
|
|
105
|
+
| Ctrl / `multiSelect` 取反 | `onSelect → onSelectChange`(末项有变化时;不经过 `onClick`) |
|
|
106
|
+
| 框选 / `selectInBox()` | `onSelect → onSelectChange`(末项有变化时;不经过 `onClick`) |
|
|
107
|
+
| `selectAt()` / `selectFeatures()` / `deselect()` / `focusOn({ select })` | `onSelect → onSelectChange`(不派发 `onClick` / `onDblClick`;`selectAt` 每次命中都发 `onSelect`,后三个按引用接口只在集合变化时发) |
|
|
108
|
+
| `selectTrigger: 'dblClick'` 的第二下 | `onClick → onSelect → onSelectChange`(有变化时)`→ onDblClick` |
|
|
109
|
+
|
|
110
|
+
`onSelect` 与 `onSelectChange` 带同一份通道上下文:选中集只涉及**一条通道**时,载荷顶层平铺
|
|
111
|
+
`channelId` / `channelIndex` / `channel` / `groupId` / `groupIndex` / `group` / `groups`;`group` 是当前组
|
|
112
|
+
(真实单击 / `selectAt` 是命中的那一组,框选与按引用接口是选中集里第一条通道回线所在的组),`groups`
|
|
113
|
+
是整条通道的全部分组。选中集涉及**多条通道**时顶层不再摊平,改看 `channelContexts`(每项带这组字段与
|
|
114
|
+
本次选中的 `lineIndexes` / `lineIds`)。单通道不会再额外造一份 `channelContexts`。两个事件共享同一批
|
|
115
|
+
`items` 与分组数组引用,不会深拷贝;`items[]` 里每条回线只保留标量归属字段,需要分组读数从顶层
|
|
116
|
+
或 `channelContexts` 查,不再给每条回线重复挂 `group` / `groups`。纯节点或空选中没有这些通道字段。
|
|
117
|
+
|
|
118
|
+
`cause` 取 `click`(指针点击)/ `boxSelect`(框选)/ `keyboard`(Esc 清空)/ `api`(接口调用)。
|
|
92
119
|
|
|
93
120
|
`action` 是更细的一份判读(与指针事件同一套写法):`action.type` 是 `select`(点中一个或接口选中)/
|
|
94
121
|
`toggleSelect`(Ctrl 点击取反,取反取没了也是它)/ `boxSelect`(框选,没框到东西也是它)/
|
|
95
122
|
`clearSelection`(点空白、Esc 或接口清空),`action.target` 是 `selection` / `empty`,`action.data` 就是
|
|
96
|
-
这一批 `items`,`action.modifiers` 是这一次的修饰键。单击触发模式下,Ctrl
|
|
97
|
-
`
|
|
123
|
+
这一批 `items`,`action.modifiers` 是这一次的修饰键。单击触发模式下,Ctrl 取反与框选这两条路**不经过 `onClick`**;
|
|
124
|
+
点空白仍会发 `onClick`(载荷为 `null`),顺序同样是 `onClick → onSelect → onSelectChange(有变化时)`。`selectTrigger: 'dblClick'`
|
|
125
|
+
时第一下仍会发 `onClick`,第二下应用选中 / 取反 / 清空后按 `onClick → onSelect → onSelectChange(有变化时)→ onDblClick` 派发。
|
|
98
126
|
要按操作分支的面板认这一个字段:
|
|
99
127
|
|
|
100
128
|
```js
|
|
@@ -65,7 +65,7 @@ view.updateOptions({ cascadeHighlight: false }) // 关掉并收掉当前高亮
|
|
|
65
65
|
|
|
66
66
|
## 指针事件
|
|
67
67
|
|
|
68
|
-
鼠标的每一种动作都有回调,载荷里都能拿到「当前是哪个元素」:`onHover`(悬停)、`onClick`(单击左键)、`onDblClick`(双击)、`onPointerDown` / `onPointerUp`(按下与抬起,含左 / 中 / 右键)、`onContextMenu`(右键)。悬停是 `GisViewHoverPayload`、点击与双击是 `GisViewClickPayload` —— 都是在 `GisViewPickResult`(点 / 线 / 通道回线的 `type`、`index`、`item`、`screen`、`coordinate`
|
|
68
|
+
鼠标的每一种动作都有回调,载荷里都能拿到「当前是哪个元素」:`onHover`(悬停)、`onClick`(单击左键)、`onDblClick`(双击)、`onPointerDown` / `onPointerUp`(按下与抬起,含左 / 中 / 右键)、`onContextMenu`(右键)。悬停是 `GisViewHoverPayload`、点击与双击是 `GisViewClickPayload` —— 都是在 `GisViewPickResult`(点 / 线 / 通道回线的 `type`、`index`、`item`、`screen`、`coordinate`,以及通道回线的 `group` / `groups`)上再补光标位置与一份 `action`;按下 / 抬起 / 右键统一发 `GisViewPointerPayload`(同样是拾取结果 + `action`)。
|
|
69
69
|
|
|
70
70
|
### action:一次操作的判读
|
|
71
71
|
|
|
@@ -118,7 +118,7 @@ createGisView(container, {
|
|
|
118
118
|
console.log(payload.world, payload.x, payload.y) // 光标处的世界坐标与画布 CSS 像素
|
|
119
119
|
},
|
|
120
120
|
onPointerUp: payload => console.log('抬起', payload.type, payload.item),
|
|
121
|
-
// 右键:点 / 线 / 空白都发,命中通道回线时载荷里还有 channelId / groupId / channelIndex
|
|
121
|
+
// 右键:点 / 线 / 空白都发,命中通道回线时载荷里还有 channelId / groupId / channelIndex / group / groups
|
|
122
122
|
onContextMenu: (payload, event) => {
|
|
123
123
|
if (!payload.hit) return // 空白处也可以在这里收掉自己的菜单
|
|
124
124
|
event.preventDefault() // 想自己弹菜单就拦住浏览器默认菜单
|
|
@@ -128,12 +128,13 @@ createGisView(container, {
|
|
|
128
128
|
})
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
-
- 载荷形状一致,取信息只需认三处:`type`(`'point'` / `'line'` / `null`)、`item`(要素原始数据,可读业务字段)、`world` / `coordinate`(前者是光标处的世界坐标,后者是要素自身的坐标)。命中通道回线时,`channelIndex` / `channelId` / `groupId` / `groupIndex` / `channel`
|
|
131
|
+
- 载荷形状一致,取信息只需认三处:`type`(`'point'` / `'line'` / `null`)、`item`(要素原始数据,可读业务字段)、`world` / `coordinate`(前者是光标处的世界坐标,后者是要素自身的坐标)。命中通道回线时,`channelIndex` / `channelId` / `groupId` / `groupIndex` / `channel` 一并给出;`group` 是**当前命中的这一组**,`groups` 是**同一通道的全部分组**(按声明顺序,每项带自己的 `groupIndex`),所以不用再查一次 `getChannelGroups()` 就能画分组切换。
|
|
132
|
+
- 右键载荷还会在 `channelContext` 上带整份分组上下文(当前组、组数、可用动作);`groups` 是各鼠标载荷共有的纯读数,`channelContext.actions` 只在右键里给。
|
|
132
133
|
- 配了 GeoJSON 背景时,以上载荷都多一个 `lngLat`:按光标的世界坐标(要素命中用 `coordinate`,悬停用最近一次光标位置)反算出来的真实经纬度,点 / 线 / 通道都一样;想自己换算就用 `worldToLngLat` / `screenToLngLat`,光标级别的屏幕坐标 + 世界坐标 + 经纬度看 `onPointer` 与 `getPointer()`。
|
|
133
|
-
- `onPointerDown` / `onPointerUp` 不改变组件行为:选中、拖拽、框选、拐点编辑照旧。左键的一次「点」(没有拖动)仍然走 `onClick` / `onDblClick`,两者是并列的,不会互相吞掉 —— 载荷里的 `action.type` 各说各话:按下是**意图**、松开是**刚做完的那件事**(`action.moved`
|
|
134
|
+
- `onPointerDown` / `onPointerUp` 不改变组件行为:选中、拖拽、框选、拐点编辑照旧。左键的一次「点」(没有拖动)仍然走 `onClick` / `onDblClick`,两者是并列的,不会互相吞掉 —— 载荷里的 `action.type` 各说各话:按下是**意图**、松开是**刚做完的那件事**(`action.moved` 说明是拖还是点)、点击是**真正发生的那一件**。这一下如果同时改了选中,顺序固定是 `onClick → onSelect → onSelectChange`;`selectTrigger: 'dblClick'` 的第二下再在最后补 `onDblClick`。
|
|
134
135
|
- 点空白处照发:`onPointerDown` / `onPointerUp` 的 `action.target` 是 `empty`(开了平移时按下是 `pan` 的意图),`onClick` / `onDblClick` 的载荷是 `null`(选中在那一刻已经清空)——「点了空白」这件事也可以看 `onSelectChange` 的 `action.type: 'clearSelection'`。
|
|
135
136
|
- **中键按住就是临时平移**(`pan` 开关开着时):`onPointerDown` 的 `action.type` 是 `pan`、`action.button` 是 `'middle'`,按住拖动平移画布、松开结束(`onPointerUp` 的 `action.type` 也是 `pan`);这一路**不经过** `onClick`,中键也不会改选中 —— 想自己接中键(中键菜单 / 快捷操作)就按 `action.button === 'middle'` 认它。长按(触摸 / 触控笔)与中键一样有明确的读数:看松开 / 点击载荷的 `action.longPress` 与 `action.press` / `action.duration`。
|
|
136
|
-
- `onContextMenu`
|
|
137
|
+
- `onContextMenu` 每次都只发这一条;命中通道回线时,分组读数在同一份载荷的 `group` / `groups` 上,可执行动作挂在 `channelContext` 上(见「通道右键交互框」),不再额外发第二个回调。**右键缺省整个不接**(`contextMenu` 开关没开时系统菜单照弹、回调也不发);接住之后一律 `preventDefault()` 收掉系统菜单(点 / 线 / 空白 / 通道都一样),回调照常发。想自己弹菜单就写 `interactive: true` / `contextMenu: true` / `features: 'view'`,想让系统菜单自己弹出来就写 `preventContextMenu: false`。
|
|
137
138
|
- 命中的层级是**点 → 线 → 通道**:右键落在节点上时载荷是 `type: 'point'`,没有 `channelContext` —— 节点压在通道回线上(端点最常见)不会被当成通道右键;点空白处同样没有 `channelContext`,可以直接用它收框。
|
|
138
139
|
- 悬停是高频率回调:大数据量下建议只做节流的读数或轻量样式切换(demo 里的读数就是这么做的)。
|
|
139
140
|
|
|
@@ -159,7 +160,7 @@ createGisView(container, {
|
|
|
159
160
|
})
|
|
160
161
|
```
|
|
161
162
|
|
|
162
|
-
- Ctrl + 点击(多选取反)与 Shift + 拖动(默认框选键,可用 `shortcuts.boxSelect` 改)**不经过** `onClick
|
|
163
|
+
- Ctrl + 点击(多选取反)与 Shift + 拖动(默认框选键,可用 `shortcuts.boxSelect` 改)**不经过** `onClick`:顺序是 `onSelect → onSelectChange`。取反的 `action.type` 是 `toggleSelect`(取反取没了也是它,此时 `action.target` 是 `empty`)、框选是 `boxSelect`(没框到东西也是它)、点空白清空是 `clearSelection`;载荷里的 `items` 是操作之后的选中集、`count` 是新的条数。想在这条路里知道「点下去的那一刻它是不是已选中的」,看 `onPointerDown` / `onPointerUp` 载荷的 `selected`,或者在回调里读一次 `getSelectionData()`。选中事件里通道回线的 `group` / `groups` 在单通道载荷顶层;多通道一起选中时看 `channelContexts`,`items[]` 里的回线不再逐条重复挂这两个字段。
|
|
163
164
|
- 不订阅事件、只想知道「这儿是什么」时用 `pickAt(clientX, clientY)`:按鼠标事件里的客户端坐标拾取,返回与指针载荷同一份结果(另加 `target` 与 `lngLat`),空白处返回 `null`;只读 —— 不改选中、不动光标,自建浮层 / 自定义菜单 / 拖拽放下时用它。框内有什么(自建框选界面、框内统计)用 `getFeaturesInRect(rect)`、当前画面里有哪几条通道用 `getChannelsInView()`,三个方法都在「实例方法」里。
|
|
164
165
|
- 悬停也可以**程序化驱动**:`hoverAt(clientX, clientY)` 让指针「停」到某个位置(悬停高亮、光标与 `onHover` 一起更新,返回与 `onHover` 同一份读数),`clearHover()` 撤掉并补发一条 `onHover(null)`,`getHover()` 随时读当前这一份 —— 外部列表 / 表格 hover 到某一行时联动高亮图上的要素用它,不必自己派发指针事件;不需要了就不用订阅 `onHover`。
|
|
165
166
|
- 选中集整个拿走用 `getSelectionData()`,一份就够:读数(`ids` / `count` / `pointCount` / `lineCount` / `channelCount`)加**要素本身**(`points` / `lines` / `channels`(按通道去重))与 `items`(与 `getSelections()` 同一份)、`pointIndexes` / `lineIndexes`、`bounds`(世界包围盒,空选中时 `null`):
|