gis-view-webgl2 0.1.2 → 0.1.3
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 +12 -8
- package/dist/gis-view.css +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +309 -59
- package/dist/index.js +1 -1
- package/docs/AI/345/257/271/350/257/235/346/261/207/346/200/273.md +117 -0
- package/docs/GisView.md +2 -2
- 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 +107 -0
- package/docs/api/index.html +1 -1
- package/docs/demos/ApiCoverageDemo.vue +644 -0
- package/docs/demos/ChannelDemo.vue +14 -12
- package/docs/demos/ClusterDemo.vue +251 -0
- package/docs/demos/CopyMergeDemo.vue +3 -4
- package/docs/demos/EventDemo.vue +3 -3
- package/docs/demos/GisViewDemo.vue +64 -8809
- package/docs/demos/api-index.js +48 -41
- package/docs/demos/demos.js +33 -16
- package/docs/demos/gis-view-demo/GisViewDemoCardHeader.vue +28 -0
- package/docs/demos/gis-view-demo/GisViewDemoDialogs.vue +82 -0
- package/docs/demos/gis-view-demo/GisViewDemoFooter.vue +16 -0
- package/docs/demos/gis-view-demo/GisViewDemoHeading.vue +16 -0
- package/docs/demos/gis-view-demo/GisViewDemoPanelStack.vue +71 -0
- package/docs/demos/gis-view-demo/GisViewDemoStage.vue +219 -0
- package/docs/demos/gis-view-demo/demo.css +1230 -0
- package/docs/demos/gis-view-demo/demoContext.js +12 -0
- package/docs/demos/gis-view-demo/panels/DataPanels.vue +303 -0
- package/docs/demos/gis-view-demo/panels/OpsPanels.vue +174 -0
- package/docs/demos/gis-view-demo/panels/StylePanels.vue +561 -0
- package/docs/demos/gis-view-demo/panels/ViewPanels.vue +396 -0
- package/docs/demos/gis-view-demo/useGisViewDemo.js +6188 -0
- package/docs/format/07-/344/272/213/344/273/266/350/275/275/350/215/267/344/270/216/347/244/272/344/276/213/346/225/260/346/215/256.md +3 -2
- package/docs/internals/16-03-/344/274/230/345/214/226/344/270/216/345/217/226/350/210/215-/344/270/213.md +1 -1
- package/docs/manual/02-/345/235/220/346/240/207/344/270/216/346/225/260/346/215/256.md +3 -2
- package/docs/manual/03-/351/205/215/347/275/256/351/241/271.md +87 -14
- package/docs/manual/04-/344/272/213/344/273/266/344/270/216/345/233/236/350/260/203.md +8 -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 +40 -3
- package/docs/manual/08-/351/200/211/344/270/255/344/270/216/346/213/220/347/202/271.md +26 -0
- package/docs/manual/09-/351/200/232/351/201/223/344/270/216/345/244/232/345/233/236/347/272/277.md +6 -2
- 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 +39 -7
- package/docs/manual/12-/346/240/207/347/255/276/344/270/216/350/243/205/351/245/260.md +13 -4
- package/docs/manual/13-/345/212/250/346/225/210/344/270/216/345/233/276/345/205/203.md +3 -0
- package/docs/manual/14-/350/247/206/345/233/276/344/270/216/347/255/233/351/200/211.md +35 -19
- package/docs/manual/15-/345/257/274/345/207/272/344/270/216/351/233/206/346/210/220.md +5 -0
- package/docs/manual/16-/345/256/236/344/276/213/346/226/271/346/263/225/346/200/273/350/241/250.md +12 -6
- package/docs/manual/17-/345/217/202/346/225/260/351/200/237/346/237/245.md +39 -22
- package/docs/manual/18-/351/200/220/346/226/271/346/263/225/347/244/272/344/276/213.md +52 -13
- package/docs/manual/20-/346/200/247/350/203/275/344/270/216/345/244/247/346/225/260/346/215/256.md +25 -1
- 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 -5
- package/docs/steps/README.md +17 -11
- package/docs/steps/selftest-actions.html +3 -5
- package/docs/steps/selftest-demo.html +27 -18
- package/docs/steps/selftest-demos.html +387 -27
- package/docs/steps/selftest-docs.html +4 -4
- package/docs/steps/selftest-effects.html +200 -0
- package/docs/steps/selftest-features.html +512 -11
- package/docs/steps/selftest-labels.html +74 -0
- package/docs/steps/selftest-perf.html +293 -20
- package/docs/steps/selftest-scale.html +52 -29
- package/docs/steps/step-10-full.js +1 -1
- package/docs/steps/step-12-events.js +1 -1
- package/package.json +1 -1
|
@@ -57,13 +57,14 @@ view.updateOptions({ channelWaypointDragMode: 'vertex' })
|
|
|
57
57
|
|
|
58
58
|
### 通道右键交互框
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
右键点中通道的回线,引擎把这条通道的上下文挂在**同一份 `onContextMenu` 载荷**的 `channelContext` 上(不再有单独的 `onChannelContextMenu` / `channelMenu`)。右键本身要接得住:`contextMenu` / `interactive: true` / `features: 'view'` 任一即可:
|
|
61
61
|
|
|
62
62
|
```js
|
|
63
63
|
view.updateOptions({
|
|
64
|
-
|
|
64
|
+
onContextMenu: (payload, event) => {
|
|
65
|
+
const context = payload.channelContext
|
|
65
66
|
if (!context) {
|
|
66
|
-
return closeMenu() //
|
|
67
|
+
return closeMenu() // 点空白或节点:没有 channelContext,用它把框收掉
|
|
67
68
|
}
|
|
68
69
|
// 这条通道有几组、当前是哪一组、这一组有几条回线 / 几个拐点
|
|
69
70
|
console.log(context.channelId, context.groupCount, context.group.index, context.group.lineCount, context.group.waypointCount)
|
|
@@ -83,17 +84,23 @@ view.getChannelContext()
|
|
|
83
84
|
view.getChannelContext('corridor-1', 'corridor-1::2')
|
|
84
85
|
```
|
|
85
86
|
|
|
86
|
-
-
|
|
87
|
+
- `payload` 仍是通用右键载荷(`action.type: 'contextMenu'`、`action.target: 'channel'`、`type: 'line'`、`channelId` / `groupId` / `lineIndex` / `lineId` / `coordinate` 等),`channelContext` 是 `{ channelId, channelIndex, channel, groupId, groupCount, groups, group, actions, lineIndex, lineId, coordinate, x, y, clientX, clientY, originalEvent }`:`groups` 是这条通道的全部分组读数(`{ id, channelId, index, lineIds, lineIndexes, lineCount, waypointCount, edited, anchored, current, skeleton, path }`;引擎的完整分组读数还带 `waypointOffsets`),`group` 是其中的当前分组,`groupCount` 是组数;`x` / `y` 是命中的画布 CSS 像素(`clientX` / `clientY` 是页面坐标),交互框照着摆就行。
|
|
87
88
|
- `actions` 每项 `{ id, label, enabled, reason? }`:`enabled: false` 时 `reason` 说明原因(拐点编辑关了、这一组还没有拐点、已经是多组先合并再拆…),界面直接照着渲染按钮即可。
|
|
88
89
|
- 六个动作 id:`select-group`(选中该分组)/ `deselect-group`(取消该分组的选中,等价于 `deselect({ channelId, groupId })`)、`add-waypoint` / `remove-waypoint`(给这一组加 / 删拐点,见上一节)、`split`(按 `options.size` 每组几条把通道拆成多组,只有一组且多于一条回线时可用)、`merge`(其余分组并回当前这一组)。
|
|
89
90
|
- 更自由的分配走 `moveChannelLine(channelId, lineId, target)`:按**回线**粒度拆成新分组或并进别的分组 —— 两回线选「拆成新分组」就是两个分组各一条(见「通道分组」)。
|
|
90
|
-
-
|
|
91
|
-
-
|
|
91
|
+
- 右键**落在节点上**时没有 `channelContext`:层级是点 → 线 → 通道,节点正压在回线端点是常态,这时载荷是 `type: 'point'`。拾取到节点却弹出通道菜单是最容易被当成 bug 的一处。
|
|
92
|
+
- 点在**空白处**(没命中通道回线)同样没有 `channelContext`,正好用来收框;接住右键之后系统菜单一律被收掉(`preventContextMenu` 缺省 `true`,要留系统菜单就写 `false`;`contextMenu` 没开时组件根本不接右键,见「指针事件」)。右键的同时命中的那一组会被记成「当前分组」,`getChannelContext()` 不传参时取的就是它。
|
|
92
93
|
- 新增通道草稿期间右键等于取消草稿(发一条 `phase: 'cancel'`)。
|
|
93
94
|
|
|
94
95
|
### 新增通道
|
|
95
96
|
|
|
96
|
-
`beginAddChannel()` 进入新增流程(**草稿缺省关**,写 `features: { channelDraft: true }` 或 `features: 'edit'` 才进得去;程序化的 `addChannel()`
|
|
97
|
+
`beginAddChannel()` 进入新增流程(**草稿缺省关**,写 `features: { channelDraft: true }` 或 `features: 'edit'` 才进得去;程序化的 `addChannel()` 不受限):缺省点第一个节点当起点,一条草稿线跟着光标走(颜色 / 线宽 / 两端圆点由 `channelDraftStyle` 配),点第二个节点出方案表。**`options.from` 可以预指定起点**(节点 id / 下标 / `{ id }` / `{ index }`),调用后直接进入 `phase: 'from'`,只需再点终点;不写 `from` 就保持原来的两次点击。开始事件的 `from` 相位、`select: true` 时预置起点的选中状态都会同步给出;`from` 找不到时草稿不开始并报 warning。**同一套流程用 `kind` 分两种**:`'channel'`(缺省)是**新建通道**,两个节点之间已经有通道就加一组 / 并进某一组;`'line'` 是**新建线路**,只加不挂任何通道的独立线路(`channels` 一个字节都不动,两个节点相同才不允许)。`circuits` 决定这一次加几条(通道回线 / 独立线路都一样)。草稿期间点空白处继续等(不会退出)、点起点同一个节点不算数、按住拖动仍然平移画布,Esc / 右键 / `cancelAddChannel()` 退出。
|
|
98
|
+
|
|
99
|
+
```js
|
|
100
|
+
view.beginAddChannel({ from: 'station-a' }) // 起点已经指定:接下来只点 station-b
|
|
101
|
+
view.beginAddChannel({ from: { id: 'station-a' }, select: true })
|
|
102
|
+
view.continueAddChannel({ from: 'station-c', kind: 'line' }) // 连续新增的下一段也能换指定起点
|
|
103
|
+
```
|
|
97
104
|
|
|
98
105
|
**直线 / 正交折线(`routing` / `path`)**:`beginAddChannel()` / `continueAddChannel()` 新增 `routing: 'straight' | 'orthogonal'` 与 `path`。`routing` 缺省 `'straight'`;写 `'orthogonal'` 且没有有效中间拐点时,组件自动补一个「先横后纵」的拐点 `[to.x, from.y]`。`path` 是**中间拐点**(不含两端),写了有效拐点就按它走,此时不会再追加自动拐点;草稿与 `commitAddChannel` / `addLine` / `addChannel` 共用同一份路由解析,预览和落地的折线完全一致。`onChannelDraft` / `onChannelDraftClick` 载荷里也带 `routing` / `path`,两端选好后 `path` 是实际会落地的中间拐点。
|
|
99
106
|
|
|
@@ -277,8 +284,33 @@ view.addLine({ from: 'station-a', to: 'station-b' }, [{ id: 'n-1' }, { id: 'n-2'
|
|
|
277
284
|
|
|
278
285
|
**余量怎么算**:`getChannelAddOptions(from, to, count?, kind?)`(实例层按节点 id,引擎层同名方法按下标)里的 `count` 就是这一次要加的回数,每个方案的 `enabled` 都按它判 —— `newGroup` 要求「还能新分组」并且 `count <= channelGroupMaxLines`,`joinGroup` 要求目标分组的余量 `>= count`(`reason` 会写清「只剩 R 回余量,本次要加 M 回」),全都不可用才 `blocked`。`kind: 'line'` 时方案表是空的、`preferred` 为 `null`(独立线路不挑方案),只有两个节点相同才 `blocked`。
|
|
279
286
|
|
|
287
|
+
`beginAddChannel()` / `continueAddChannel()` 的 `GisViewChannelDraftOptions` 逐项如下:
|
|
288
|
+
|
|
289
|
+
| 字段 | 类型 | 缺省 | 说明 |
|
|
290
|
+
| --- | --- | --- | --- |
|
|
291
|
+
| `from` | `GisViewPointRef` | 无 | 预指定起点(id / 下标 / `{ id }` / `{ index }`),直接进 `from` 相位;找不到时报 warning 且不开始 |
|
|
292
|
+
| `autoCommit` | `boolean` | `false` | 两个节点一选完就按推荐方案自动落地,不用再调 `commitAddChannel()` |
|
|
293
|
+
| `continuous` | `boolean \| 'chain'` | `false` | 每段落地后自动开下一段;`'chain'` 等价于同时 `chain: true` |
|
|
294
|
+
| `chain` | `boolean` | `false` | 连续新增时以上一段终点当下一段起点;显式 `from` 优先于它 |
|
|
295
|
+
| `kind` | `'channel' \| 'line'` | `'channel'` | 新建通道 / 回线,或新建不挂通道的独立线路 |
|
|
296
|
+
| `circuits` | `number` | `1` | 一次新建几回;`lineItems` 给了有效项时按它的条数对齐 |
|
|
297
|
+
| `name` | `string` | 按两端节点生成 | 新线路名 |
|
|
298
|
+
| `lineId` | `string \| number` | 按通道 id 生成 | 新回线 id 的兼容别名;与 `id` 二选一 |
|
|
299
|
+
| `id` | `string \| number` | 无 | 新回线 id;与 `lineId` 同时给时优先 |
|
|
300
|
+
| `lineProps` | `Partial<GisViewLine>` | 无 | 透传给每条新回线的业务字段(颜色、宽度、电压等级…) |
|
|
301
|
+
| `linePropsByMember` | `Array<Partial<GisViewLine> \| undefined>` | 无 | 逐回属性,第 i 项只盖在第 i 条上;与 `createChannels` 同名同义 |
|
|
302
|
+
| `lineItems` | `GisViewChannelLineItems` | 无 | 连同线路一起新建的一条 / 一批;给了几条就建几条 |
|
|
303
|
+
| `routing` | `'straight' \| 'orthogonal'` | `'straight'` | 直连,或自动补一个先横后纵的拐点 |
|
|
304
|
+
| `path` | `GisViewCoordinate[]` | 无 | 中间拐点(不含两端);有效时优先于 `routing` 的自动拐点 |
|
|
305
|
+
| `channelDraftStyle` | `GisViewChannelDraftStyle` | 全局 `channelDraftStyle` | 本次草稿的预览样式,草稿结束即丢弃 |
|
|
306
|
+
| `handoff` | `boolean` | `false` | `ready` 发完就收掉假通道,由使用方自己落地;与 `autoCommit` 同给时先自动落地 |
|
|
307
|
+
| `select` | `boolean` | `false` | 点节点时同步进选中集(走 `onSelect` / `onSelectChange`);预指定 `from` 时起点当场选中 |
|
|
308
|
+
| `channelProps` | `Partial<GisViewChannel>` | 无 | 新通道透传字段(宽度、节点宽度、偏移方式…) |
|
|
309
|
+
| `originalEvent` | `Event \| null` | `null` | 触发这次草稿的原始事件,原样带进回调载荷 |
|
|
310
|
+
|
|
280
311
|
```js
|
|
281
312
|
view.beginAddChannel({
|
|
313
|
+
from: 'station-a', // 预指定起点:接下来只点终点;不写则点两次
|
|
282
314
|
autoCommit: false, // true:两个节点一选完就按推荐方案自动落地,不用再调 commitAddChannel
|
|
283
315
|
name: '新增通道', // 新线路名,缺省按两端节点拼
|
|
284
316
|
lineId: 'new-line-1', // 新回线 id,缺省按通道 id 生成(撞车自动加后缀)
|
|
@@ -147,14 +147,23 @@ view.updateOptions({ labelOptimize: true }) // 切到优化档;false / 不写
|
|
|
147
147
|
`html` 与顶层 `labelRender` 解决的是两件事:`html: false` 只关闭字符串的 HTML 解析,标签外壳仍是逐条 `.gis-view__label`(默认 `div`),几万条纯文本标签就会产生几万个节点;`labelRender` 决定这些纯文本标签要不要换成一张画布。
|
|
148
148
|
|
|
149
149
|
- **`auto`(缺省)**:只在**强制显示档**(`labelOptimize` 未开、`denseMode` 未激活)启用。节点层与线路层各自统计这一轮能画布的纯文本标签,某一层达到 **1024** 条,该层就改画到一张 `.gis-view__label-canvas`,不再为这些标签建 `div`;两层互不牵连。
|
|
150
|
+
- **`canvas`**:纯文本标签始终改画到单张 Canvas,不受 1024 条阈值限制,优化档与密集档也生效。`maxCount` / `when` / `scanLimit` / `overlapMode` 等策略照旧,不能画布的标签仍按原规则走 DOM。高密度场景建议同时打开 `labelOptimize`,让截断与避让限制画布标签数量。
|
|
150
151
|
- **`dom`**:始终逐条建 `.gis-view__label`,保持旧行为。数据量不大、要自己用 CSS / 事件精细控制标签时用它。
|
|
151
152
|
- **仍走 DOM 的标签**:`html: true`、函数返回 `HTMLElement`、可拖拽 / 可编辑,以及 Canvas 画不全的样式(背景图、阴影、`transform`、多行、字间距、非实线或四边不一致的边框等)会留在同层 DOM 里,和画布标签可以混排。画布只接管纯文本且样式能完整复刻的那部分。
|
|
152
|
-
-
|
|
153
|
-
- **画布与交互**:画布按视口 CSS 尺寸与设备像素比(含宿主显示比例,夹在 0.5 ~ 4
|
|
153
|
+
- **优化档与避让**:显式 `canvas` 在 `labelOptimize: true` / 密集档下不会退回 DOM;避让碰撞框、节点换锚点与线路沿线换位都直接使用画布记录的宽高,文字宽度按「字体 + 样式 + 文案」缓存,同一批同文案标签不再逐条 `measureText`。线路内容是函数时无法保证换位后文字同步,换位回退会保守放弃,避免文字与位置错配。
|
|
154
|
+
- **画布与交互**:画布按视口 CSS 尺寸与设备像素比(含宿主显示比例,夹在 0.5 ~ 4)分配像素。首屏排版完成时立即出图;平移、缩放、拖节点、拖线路与悬停半径变化产生的连续重绘按 `requestAnimationFrame` 合并到下一帧,同一帧多次相机变化只画一次。绘制前会剔除视口外标签(旋转标签按外接圆,平移期把整层位移也算进去)。`exportImage({ includeLabels: true })` 会把画布标签写进 SVG。数量回落到阈值以下或切到 `dom` 时,DOM 标签会重新建回来;切换只重排标签层,不动引擎。
|
|
154
155
|
|
|
155
156
|
```js
|
|
156
|
-
view.updateOptions({ labelRender: 'auto' })
|
|
157
|
-
view.updateOptions({ labelRender: '
|
|
157
|
+
view.updateOptions({ labelRender: 'auto' }) // 缺省:强制显示档达到 1024 条才自动画布化
|
|
158
|
+
view.updateOptions({ labelRender: 'canvas' }) // 纯文本始终画布化(优化档也生效)
|
|
159
|
+
view.updateOptions({ labelRender: 'dom' }) // 强制逐条 DOM,保持旧行为
|
|
160
|
+
|
|
161
|
+
// 大数据下通常和优化档一起用:200 条上限、避让与换落点都保留,只是容器换成画布
|
|
162
|
+
view.updateOptions({
|
|
163
|
+
labelOptimize: true,
|
|
164
|
+
labelRender: 'canvas',
|
|
165
|
+
label: { enabled: true, content: '{name}', maxCount: 200 }
|
|
166
|
+
})
|
|
158
167
|
```
|
|
159
168
|
|
|
160
169
|
## 标签的拖动与编辑
|
|
@@ -46,6 +46,8 @@ view.updateOptions({
|
|
|
46
46
|
|
|
47
47
|
`max` 缺省的 `'auto'` **不是拿场的峰值归一化**:密度场天生长尾(几个热点能比周围高一两个数量级),按峰值线性归一化会把九成面积挤进最冷一档、整张图糊成一片。缺省改成按分位取「膝盖」—— 90% 以下的面积铺满前 3/4 档,剩下那一截留给热点周围的色带;要老行为写 `max: 'peak'`,写数字就是按它线性归一化。`threshold`(门槛)与 `gamma`(对比度)一起决定盖住多大面积:门槛抬起来只留热点,就得到参考图那种「大片浅色 + 一圈圈色带 + 白心」。`weight: 'value'`(缺省)按要素的值域比例算比重(值高 + 密集 = 热),`weight: 'count'` 只数密度。场按世界坐标烘一次,平移不重算,缩放档变化超过 1.35 倍才重烤;要素特别多时撒点自动降采样(档边仍是细栅格的分辨率),`opacity` 只在画的时候乘、不触发重烤。
|
|
48
48
|
|
|
49
|
+
密度场的缓存分两层:坐标、权重字段、显隐或通道值变化时才重新采集要素;只改密度核参数、色带或画层时复用上一份采样。`density.opacity` 与 `layer` 只改绘制、不重烤,换色带或核参数才用旧采样重算场。拖动节点 / 拐点时只记一笔「几何已变」,停手后统一补烤一次,不在每个指针事件里重算;密度场关闭期间发生的坐标 / 权重变化也会记账,下一次开启不会复用旧要素。
|
|
50
|
+
|
|
49
51
|
**鹰眼图**跟着同一份 `heatmap` 取色带颜色与尺寸倍数,但**不画光晕、也不画密度场**:小图要的是清晰,一层放大的光晕或一张分档色块在几百像素的缩略图上只会糊成一片。
|
|
50
52
|
|
|
51
53
|
**作用对象与通道**:`target` 决定哪些要素吃这份配置。`target: 'channel'` 时通道里的每条回线取**所属通道**的字段值(整条走廊一个颜色,回线不会各染一色);回线自己有值(`target` 含 `'line'`,且该回线命中字段或自己配了 `value`)时按自己的值算。逐要素 `item.heatmap` 与全局同义:`false` 不参与(保持自身配色),`true` 沿用全局那份,对象在全局配置上逐字段覆盖(只想改字段 / 值域 / 色带里的一个就写一个)。
|
|
@@ -206,6 +208,7 @@ for (const glyph of view.getLineEffects()) {
|
|
|
206
208
|
|
|
207
209
|
- **动点进的是既有批次**:形状(圆)进圆点实例缓冲、图片 / SVG 进贴图组,与节点 / 装饰走同一条符号链(同一张烘焙好的贴图,不会为动画再烤一份)。
|
|
208
210
|
- **每帧只改位置**:`updateLineEffects()` 按弧长算出这一帧的位置,按**槽位连续**攒成一段一次 `bufferSubData`(一段最多 64 个),写入量只跟视野里的动点数走;包围盒与视野不相交的线整条跳过。一帧最多算 4000 个动点,超了下一帧接着补。
|
|
211
|
+
- **每帧只遍历配了动点的线路**:动画线路另建 `lineEffectRuns` 清单,`updateLineEffects()` 不再逐条扫全部线路 —— 普通线路再多,动画循环也只处理真正配了 `effect` 的那几条。拖动端点 / 拐点、通道骨架变化时,路径就地换掉的同时重算该条总长与包围盒,动点按新弧长继续采样,不会按旧长度跳位;多层阴影的实例更新也合并成一次 `bufferSubData`。
|
|
209
212
|
- **涟漪每帧只传一个 `u_time`**:半径、相位、周期、线宽在建实例时全部定死(相位按 `stagger` 与第几圈算好),实例缓冲一个字节都不重传,GPU 侧一次实例化绘制画完。
|
|
210
213
|
- **涟漪实例只建「视口里的」**:先问点网格要视口外扩一成的候选,排一遍保证「按数据顺序」,再用与框选同一份可见判定过滤;相机在动但**拖动 / 缩放期间不重建**(涟漪记的是世界坐标,相机怎么动它们自己跟着走),停手后那一帧一次补齐。`limit`(缺省 2000)是兜底:密集数据里一屏几万个节点不会把涟漪铺成一片糊。
|
|
211
214
|
- **不画的时候一个字节都不花**:动画开着才续帧 —— 视野里没有动点也没有涟漪、页签切到后台(`document.hidden`)、系统要求减少动态效果(`prefers-reduced-motion`)时直接停,静止画面照旧按需渲染;`effects` 没配(数据里也没人逐条配)时这一整层只是几个布尔判断。
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## 筛选
|
|
6
6
|
|
|
7
|
-
`setFilter` 按属性过滤点与线,点被过滤掉时绑在它身上的线路按 `cascade`
|
|
7
|
+
`setFilter` 按属性过滤点与线,点被过滤掉时绑在它身上的线路按 `cascade` 联动消失;这个默认联动还受 `lineFollowsNode` 影响(见下):
|
|
8
8
|
|
|
9
9
|
```js
|
|
10
10
|
// 只看 525kV 以上的节点:两端节点没了的线路(以及通道回线)一起隐藏
|
|
@@ -47,10 +47,12 @@ normalizeFilter({ points: {}, cascade: 'both', nope: 1 }) // unknownKeys: ['nop
|
|
|
47
47
|
| --- | --- | --- | --- |
|
|
48
48
|
| `points` | `GisViewConditionInput<GisViewPoint>` | 无 | 点条件,缺省表示不过滤点 |
|
|
49
49
|
| `lines` | `GisViewConditionInput<GisViewLine>` | 无 | 线条件,缺省表示不过滤线 |
|
|
50
|
-
| `cascade` | `false \| 'binding' \| 'coordinate' \| 'both'` | `'binding'` | 点被过滤后哪些线路一起消失:按 `from` / `to`
|
|
50
|
+
| `cascade` | `false \| 'binding' \| 'coordinate' \| 'both'` | `lineFollowsNode` 开启时 `'binding'`,关闭时 `false` | 点被过滤后哪些线路一起消失:按 `from` / `to` 绑定、按端点坐标(端点正好落在被过滤的节点上)、两者都算、或完全不联动;显式写出的值始终优先 |
|
|
51
51
|
| `worker` | `boolean` | 跟随 `filterWorker` | 这一次筛选是否允许放进 Worker |
|
|
52
52
|
|
|
53
|
-
联动只影响表现,数据本身不动:`updateData` / `updateOptions` 换了数据之后按同一个条件重算。通道回线也是普通线路,跟着同一个 `cascade` 走:`binding` / `coordinate` / `both` 时绑着被过滤节点的通道回线一起收起来,`false` 时照旧画 ——
|
|
53
|
+
联动只影响表现,数据本身不动:`updateData` / `updateOptions` 换了数据之后按同一个条件重算。通道回线也是普通线路,跟着同一个 `cascade` 走:`binding` / `coordinate` / `both` 时绑着被过滤节点的通道回线一起收起来,`false` 时照旧画 —— 被过滤的节点仍然当锚点用(几何不跟着筛选断,回线端点还钉在它原来的坐标上),只是节点自己不显示。`cascade: false` 时仍显示的通道宽度也按被过滤节点原本的尺寸链计算,不会因为节点不画了就改按另一端尺寸或退回默认 `channelWidth`。只有节点真的不在数据里(删掉、或者写了 `visible: false`)时,两端锚不住的通道与它的回线才整条不显示(和「两端没有节点就不显示」是同一条规则)。
|
|
54
|
+
|
|
55
|
+
`lineFollowsNode: false` 把「节点退场」与「线路 / 通道退场」拆开:筛选未显式写 `cascade` 时默认不再级联,隐藏、删除节点也只动节点;线路与通道继续停在最后一次解析出的坐标、骨架与宽度。条件里显式写了 `cascade` 时仍按显式值级联。筛选条件放宽或清空、被筛掉的回线重新出现后,引擎会在线路线宽解析完成后重新排一次通道偏移,通道与回线按当前宽度回到正确车道,不会保留筛选期间的旧间距。拖拽节点松手后,按端点坐标联动的筛选会按新坐标重算一次。需要「把某个要素找出来并居中」而不是隐藏其它要素时用 `search`,见「搜索与定位」。
|
|
54
56
|
|
|
55
57
|
### 大数据下的 Worker 筛选
|
|
56
58
|
|
|
@@ -93,7 +95,12 @@ hit?.field / hit?.value // 命中的是哪个字段、字段值是什么(如 '
|
|
|
93
95
|
// focusOn:把视角移到目标上 —— 单条、一批、只居中都由它一条搞定
|
|
94
96
|
view.focusOn(hit) // 一条命中:按它的范围适配视图
|
|
95
97
|
view.focusOn('station-1024', { scale: 12 }) // 直接给比例
|
|
98
|
+
view.focusOn({ type: 'point', id: 'station-1024' }) // 节点 / 线路同 id 时显式消歧
|
|
99
|
+
view.focusOn({ type: 'line', id: 'station-1024' })
|
|
96
100
|
view.focusOn({ type: 'line', index: 3 })
|
|
101
|
+
view.focusOn({ type: 'channel', channelId: 'channel-a' }) // 通道也可以直接写 { channelId }
|
|
102
|
+
view.focusOn({ type: 'group', channelId: 'channel-a', groupId: 'group-2' })
|
|
103
|
+
view.focusOn({ type: 'group', groupId: 'group-2' }) // groupId 全局唯一时可省略通道
|
|
97
104
|
view.focusOn([116.4, 39.9]) // 一个坐标点:只居中,比例不动
|
|
98
105
|
view.focusOn(['station-1', 'station-2', 'station-3']) // 一批:取整体包围盒 —— 这三个点的中心当屏幕中心
|
|
99
106
|
view.focusOn(['station-1', 'station-2'], { select: true }) // 顺带把它们选上(与接口选中同一份 state)
|
|
@@ -108,6 +115,8 @@ view.focusOn({ lngLat: [116.4, 39.9] }, { center: true }) // 配了 GeoJSON 底
|
|
|
108
115
|
view.focusOn({ minX: 116, minY: 39, maxX: 117, maxY: 40 }, { center: true }) // 一段范围:取中心
|
|
109
116
|
```
|
|
110
117
|
|
|
118
|
+
字符串 / 数字仍然兼容旧写法:先按节点 id 找,再按线路 id 找;同一个 id 同时出现在节点与线路里时用 `{ type: 'point' | 'line', id }` 消歧。裸字符串不表示通道;整条通道可以写 `{ channelId }`,要和通用 `id` / `index` 写法区分时再用 `{ type: 'channel', ... }`。分组必须写 `{ type: 'group', channelId?, groupId }`,`groupId` 在全部通道里唯一时可以省略通道。节点、线路、通道与分组都先解析成世界坐标范围再交给同一条 `zoomToBounds` 路径,聚焦比例口径一致,没有为某类目标额外乘放大倍率。
|
|
119
|
+
|
|
111
120
|
| `focusOn` 的选项 | 说明 |
|
|
112
121
|
| --- | --- |
|
|
113
122
|
| `scale` | 直接设成这个比例,不再按范围适配 |
|
|
@@ -205,7 +214,7 @@ createGisView(container, {
|
|
|
205
214
|
4. **按「节点间距」而不是「包围盒」算适应**:`focusOn([...几个代表性要素])` / `zoomToBounds(业务范围)`;也可以给 `minScale` 一个下界,缩到这条线就停住。
|
|
206
215
|
5. **想让节点本身不跟着缩**:`pointZoomScale` / `lineZoomScale` 调小(`0` = 完全不跟随地图缩放),尺寸主要由 `pointSizeScale` / `lineWidthScale` 的常数倍数决定 —— 比例被带跑时至少节点不会一起变小。
|
|
207
216
|
|
|
208
|
-
6.
|
|
217
|
+
6. **给节点最小间距兜底(先试它)**:打开 `fitSpacing` —— 适应视图时按可见节点最近中心距反推比例,远处孤立点撑大包围盒也不会再把主体压成一团;孤立点允许落到视口外,必要时用 `maxZoom` 限制放大倍数,见「适应视图的节点间距(fitSpacing)」。
|
|
209
218
|
|
|
210
219
|
## 缩放范围(minScale / maxScale)
|
|
211
220
|
|
|
@@ -229,30 +238,33 @@ view.updateOptions({ minScale: scale / 5, maxScale: scale * 5 })
|
|
|
229
238
|
|
|
230
239
|
demo 的「初始视图与背景」面板里就有现成的入口(`docs/demos/GisViewDemo.vue`):两个输入框(最小比例 / 最大比例)直接写数字,改完走 `updateOptions({ minScale, maxScale })` **并顺手 `setCamera` 把当前相机夹回区间**(更新配置本身不会把相机拉回来,demo 里把这一步显式补上了);`以当前比例设限(÷5 ~ ×5)` 按当下比例算一对;`试一下下限` / `试一下上限` 各喂一个远超区间的比例给 `setCamera()`,读数里能看到相机停在哪;`解除限制` 回到组件缺省的 `0.002 ~ 20000`。自测页 `docs/steps/selftest-demo.html` 有 3 条断言盯着这一套(按当前比例设限并下发 / 越界喂值被夹在上下限 / 解除限制回到缺省)。
|
|
231
240
|
|
|
232
|
-
##
|
|
241
|
+
## 适应视图的节点间距(fitSpacing)
|
|
233
242
|
|
|
234
|
-
|
|
243
|
+
「两个本来一样的视图,只因为多了一个远处节点,节点就突然很大、很挤」——根因是自动适应读的是**数据包围盒**:远处节点把范围撑大,`fitView()` 只能把 `camera.scale` 压小,节点之间的距离随之变短;节点自己的屏幕尺寸不跟着缩,看起来就像放大了一样。
|
|
235
244
|
|
|
236
|
-
`
|
|
245
|
+
`fitSpacing` 不改包围盒,而是在普通适应算完之后再做一次**节点间距兜底**:找出当前可见节点里最近的两个不同位置,按它们的世界距离算出「要让中心距达到 `minDistance` 需要多大的比例」,取普通适应与这个比例中较大的一个。它**只提高 `camera.scale`,不改变相机中心**:中心始终沿用普通适应按数据包围盒算出的那一个,所以不会因为最近节点对换了一对就突然跳到图上另一个位置。规则网格里最近距离大量并列也不会影响结果 —— 距离相同就只取同一个目标比例,没有「挑哪一对并居中」的问题。
|
|
237
246
|
|
|
238
247
|
```js
|
|
239
|
-
//
|
|
240
|
-
const view = createGisView('#map', { points, lines, channels,
|
|
241
|
-
|
|
248
|
+
// 最省事:最小中心距 24 CSS 像素,放大倍数不设相对上限(仍受 maxScale 约束)
|
|
249
|
+
const view = createGisView('#map', { points, lines, channels, fitSpacing: true })
|
|
250
|
+
|
|
251
|
+
// 细调:最近节点至少隔 32px;最多放大到普通适应比例的 8 倍
|
|
252
|
+
view.updateOptions({ fitSpacing: { minDistance: 32, maxZoom: 8 } })
|
|
253
|
+
view.fitView() // 改配置不会当场动相机,再适应一次才看得到
|
|
242
254
|
|
|
243
|
-
view.
|
|
244
|
-
view.setZoomBaseScale() // 以当下这一屏为基准(换了一批量纲完全不同的数据、想重新校准观感时调它)
|
|
245
|
-
view.setZoomBaseScale(2.5) // 也可以直接给一个比例
|
|
255
|
+
view.updateOptions({ fitSpacing: false }) // 关掉,下一次 fitView 恢复普通包围盒适应
|
|
246
256
|
```
|
|
247
257
|
|
|
248
258
|
几个约定:
|
|
249
259
|
|
|
250
|
-
-
|
|
251
|
-
-
|
|
252
|
-
-
|
|
253
|
-
-
|
|
254
|
-
-
|
|
255
|
-
-
|
|
260
|
+
- **默认关**,打开后只影响「默认 fit 模式下的首次适应」与手动 `fitView()`;`zoomToBounds()` / `focusOn()` 仍按指定范围算,不会强行套节点间距。
|
|
261
|
+
- 只统计**筛选 / 隐藏之后仍然可见**的节点。完全重合的坐标不算有效间距(否则两个重叠点会让整套兜底失效);少于两个不同位置时不调整。
|
|
262
|
+
- **只放大、不跳视点**:`fitSpacing` 不重算中心,也不挑一对节点居中。需要改变中心时用 `initialView.center` / `initialView.bounds`、`focusOn()` 或 `setCamera({ center })`。
|
|
263
|
+
- `minDistance` 是节点**中心之间**的屏幕距离(CSS 像素),默认 `24`。想给节点本身和描边留更多空隙就调大。
|
|
264
|
+
- `maxZoom` 是相对普通适应当前比例的倍数上限,默认 `0` 表示不限;设成正数可避免极端数据把画面放大到只剩局部。`minScale` / `maxScale` 始终是最后一层夹取。
|
|
265
|
+
- 远处孤立点仍参与普通适应的包围盒与中心计算;放大后它可以落到视口外,这是「先保证节点间距」的取舍。如果孤立点连中心都不该影响,关掉 `fitSpacing` 或改用 `initialView.bounds` / 预筛数据钉住业务范围。
|
|
266
|
+
- 显式配了 `initialView.scale` / `initialView.zoom` 时以使用方给的为准;只有没有写死比例 / 倍数的 fit 模式才走间距兜底。
|
|
267
|
+
- demo 的「样式」面板有「适应节点间距」开关、最小中心距与最大放大输入;自测页 `docs/steps/selftest-scale.html` 有 8 条断言盯着这一套(配置回显 / 提高比例且忽略重合点 / 保持普通适应中心 / 不跳到最近节点对 / 屏幕间距 / `maxZoom` / 关闭恢复 / 规则网格并列时仍保持原中心)。
|
|
256
268
|
|
|
257
269
|
## 背景层
|
|
258
270
|
|
|
@@ -439,6 +451,8 @@ createGisView(container, {
|
|
|
439
451
|
|
|
440
452
|
交互与开销:**在框上按下直接拖框**(世界位移 = 屏幕位移 ÷ 小图比例),**空白处单击不改变视角**,按住超过 `longPressDelay` 才进入「跟着拖」,拖动过程中始终跟着光标;光标停在小图上滚动滚轮按光标位置缩放主图(`wheelZoom: false` 关掉)。每个有位移的手势结束时可通过 `onInteraction` 收到一条通知,不必自己在小图 DOM 上再挂一套指针监听。底图画的是筛选之后真正画出来的线,通道骨架与回线都在内(直接问引擎要几何,不用自己再推一遍通道偏移),画法是先铺线、再把节点整层盖上去 —— 节点层级高于线路,密集底图上的节点不会被线咬掉。底图只在数据或筛选结果变化时重画(节点直接写进像素缓冲,十万级也只在重建时花一次时间),相机变化只改视口框的 `transform`,所以拖动小图不掉帧。小图还会缓存**上一次的节点像素结果**与**数据范围**:一次改动排在前后两帧各重画一次(引擎重排之后要再取一次几何),第二次与第一次的数据、范围、尺寸完全一样时直接复用那份像素,十万点下第二次重画从 ~20ms 降到 0.3ms(配了 `pointMapZoomScale` / `lineMapZoomScale` 时把「主视图倍数」也并进缓存的键,倍数变了才重铺);`extent: auto` 的取舍跟相机有关,相机挪进 / 挪出那份小范围时才补一次重画(每帧只做几次比较,判断用的范围是缓存的)。小图拖框 / 小图滚轮带来的相机变化不算主画布上的交互:配了 `hideOnInteract` 的图层不会在这时被收起来,拖动结束还会补一次真实排版 —— 不会出现「动一下鹰眼图,主视图标签全没了」。真在主画布上拖动过之后、两层标签同时收着时,收尾计时器也照样挂上 —— 覆盖层停手的收尾是无条件的,不会因为「两层都在收着、当下没东西可排」把恢复一起跳过。
|
|
441
453
|
|
|
454
|
+
线路层另有自己的离屏 canvas 与缓存:缓存键包含画布尺寸、范围、投影、小图倍率与线路样式,命中时整层直接合成,不再重复投影与描边;`collectMinimapData()` 复制路径时顺路算出每条线的包围盒,完全落在小图视野外的线不建路径。只有布局尺寸实际变化时才重设 canvas 尺寸,单纯补画或移动视口框不会清空这份缓存。
|
|
455
|
+
|
|
442
456
|
`zoomable: true` 之后小图自身也能整体放大缩小,空白处的拖动换成下面两种动作(单击不再需要长按,空白处不再走 `longPressDelay` 那条路):
|
|
443
457
|
|
|
444
458
|
- **平移小图**(`dragAction: 'pan'`,默认):光标往哪拖,小图内容跟着走,主图不动;内容夹在数据范围内,拖到头就停住。主图视口框跟着内容一起挪,必要时会贴在边上指示方向。
|
|
@@ -485,4 +499,6 @@ createGisView(container, {
|
|
|
485
499
|
|
|
486
500
|
---
|
|
487
501
|
|
|
502
|
+
**相关章节**:[03 配置项(options)](03-配置项.md) · [07 指针与要素编辑](07-指针与要素编辑.md) · [08 选中与拐点](08-选中与拐点.md) · [16 实例方法总表](16-实例方法总表.md)
|
|
503
|
+
|
|
488
504
|
[← 13 动效与图元](13-动效与图元.md) · [手册目录](../GisView.md) · [15 导出与集成 →](15-导出与集成.md)
|
|
@@ -11,6 +11,7 @@ const url = await view.exportImage({ scale: 2 }) // 位图:
|
|
|
11
11
|
const plain = await view.exportImage({ background: 'none' }) // 位图:透明底
|
|
12
12
|
const svg = await view.exportImage({ type: 'svg' }) // 矢量:放大不糊
|
|
13
13
|
const svgPlain = await view.exportImage({ type: 'svg', background: 'none' }) // 矢量 + 透明底
|
|
14
|
+
const full = await view.exportImage({ scope: 'all', padding: 32 }) // 全部内容:临时适应数据范围后出图
|
|
14
15
|
// 也可以直接触发下载:download: true(用默认文件名)或 download: '线路图.png'
|
|
15
16
|
await view.exportImage({ download: '线路图.png' })
|
|
16
17
|
await view.exportImage({ type: 'svg', background: 'none', download: '线路图.svg' })
|
|
@@ -21,6 +22,8 @@ await view.exportImage({ type: 'svg', background: 'none', download: '线路图.s
|
|
|
21
22
|
| `type` | `'image/png' \| 'image/jpeg' \| 'image/webp' \| 'svg'` | `'image/png'` | 导出格式:位图(`jpeg` / `webp` 可以用 `quality`)或矢量 SVG(`'svg'` 与 `'image/svg+xml'` 都认) |
|
|
22
23
|
| `quality` | `number` | 无 | 0 ~ 1,只对 `jpeg` / `webp` 有效 |
|
|
23
24
|
| `scale` | `number` | 设备像素比(SVG 为 `1`) | 导出倍率(相对画布 CSS 像素);SVG 只写进 `width` / `height` 两个属性,`viewBox` 始终是 CSS 像素 |
|
|
25
|
+
| `scope` | `'viewport' \| 'all'` | `'viewport'` | `'viewport'` 只导当前可视区域;`'all'` 临时把相机适应到全部当前可见内容,导完恢复原相机。写其它值直接抛异常 |
|
|
26
|
+
| `padding` | `number` | `24` | 只对 `scope: 'all'` 生效:适应全部内容时四周留白(CSS 像素,负数按 0 处理);`scope: 'viewport'` 忽略 |
|
|
24
27
|
| `background` | `string \| false` | 带背景 | 见下表:不带背景 = 透明底,颜色字符串 = 换一层底色 |
|
|
25
28
|
| `includeLabels` | `boolean` | `true` | 是否把标签一起画进去 |
|
|
26
29
|
| `download` | `boolean \| string` | `false` | 是否触发浏览器下载,字符串同时作为文件名 |
|
|
@@ -33,6 +36,8 @@ await view.exportImage({ type: 'svg', background: 'none', download: '线路图.s
|
|
|
33
36
|
| `false` / `'none'` / `'transparent'` | **不带背景**:上面那些都不画,输出**透明底**(位图是带 alpha 通道的 png / webp,矢量则干脆不写这些元素) |
|
|
34
37
|
| `'#ffffff'` 这类颜色字符串 | **带背景,但换底色**:只把最底下那一层清屏色换成它,底图、GeoJSON 区域填充与网格照旧(固定白底 / 深色底就写它;`jpeg` 不支持透明,建议给一个色) |
|
|
35
38
|
|
|
39
|
+
`scope: 'all'` 不是按原始比例拼一张超大的图,而是**临时改相机把全部可见内容框进当前视口**,因此输出尺寸仍由画布 CSS 尺寸 × `scale` 决定;筛选 / `visible: false` 隐藏的要素仍不会进入导出。位图与 SVG 两条路都支持,`finally` 中会恢复相机并重排标签、扩展图形与鹰眼图,使用方看到的视角不会停在导出那一版。
|
|
40
|
+
|
|
36
41
|
导出用的是当前这一帧的实际画面:位图内部先同步重画一帧再取像素 —— 透明底与换底色这两种写法出的都是「只给导出用」的那一帧,读完像素立刻补画一帧正常画面的把画布还原,屏幕上不会停在导出那一版。整个过程不需要开 `preserveDrawingBuffer`,所以也没有常驻的额外显存开销。
|
|
37
42
|
|
|
38
43
|
`type: 'svg'` 走的是矢量:线(含虚线图案与相位)、点(内置圆 / 方与 SVG 符号)、线路装饰、拐点、GeoJSON 区域、扩展图形与标签都是真正的 SVG 元素,颜色 / 线宽 / 线型取的就是当前那一帧解析出来的值(悬停、选中样式同样在内),放大到任意倍都不糊。PNG / JPEG / WebP 这一支先画引擎画布,再按「扩展图形 → 标签」叠上去,所以 `graphics` 里的 SVG 路径、图片与 Canvas 都在合成结果里。两点差异:热力密度场是烘焙出来的贴图、不进 SVG;位图符号(`symbol.type: 'image'`)、自定义图元(`registerSymbol` 的画笔)与图片 / Canvas 图形都以 `<image href>` 出现(前者引用原地址,后两者是原图或 data URL),把导出的 svg 当图片内嵌到别的页面时,跨域图片与外部字体会被浏览器挡掉(直接打开 svg 文件没问题)。需要那一份矢量数据自己拼别的格式时,用 `view.snapshotScene({ background, labels })`(它已经带上 `graphics`),或用导出的 `buildSceneSvg(scene, { scale })`;`svgDataUrl(markup)` 是把一段 SVG 标记转成 `data:` URL 的小工具(组件内部导 svg 图片时走它,自己拿到标记要拼进 `<img src>` 或 CSS 时也可以直接用)。
|
package/docs/manual/16-/345/256/236/344/276/213/346/226/271/346/263/225/346/200/273/350/241/250.md
CHANGED
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
| `zoomIn(step?)` / `zoomOut(step?)` / `zoomBy(factor, origin?)` | 相对缩放,`origin` 为画布 CSS 像素锚点(缺省视口中心) |
|
|
36
36
|
| `zoomTo(scale, origin?)` | 直接设成指定比例(像素 / 世界单位) |
|
|
37
37
|
| `zoomToBounds(bounds, padding?)` | 把一段世界坐标矩形适应到视图内,退化成一点时只居中不改比例 |
|
|
38
|
-
| `focusOn(target, options?)` | 把视角移到目标上:单条(搜索命中 / 要素 id / `{ type, index }` /
|
|
38
|
+
| `focusOn(target, options?)` | 把视角移到目标上:单条(搜索命中 / 要素 id / `{ type: 'point' \| 'line' \| 'channel', id \| index }` / `{ channelId }` 整条通道 / `{ type: 'group', channelId?, groupId }` / 坐标 / 矩形 / `{ lngLat }`)或**一批**(数组取整体包围盒 —— 搜到三个节点就是这三个点的中心当屏幕中心);字符串先节点后线路,裸字符串不表示通道,同 id 用 `type` 消歧,分组必须显式写 `type: 'group'`(全局唯一 `groupId` 可省略通道);节点 / 线路 / 通道 / 分组共用同一套范围适配,不额外放大。`options` 认 `scale`、`center: true`(只居中、比例一点不动)、`padding`、`maxZoom`、`select`(顺带选中这批,`mode` 决定怎么并进当前选中集) |
|
|
39
39
|
| `search(keyword \| options)` | 按关键字搜索节点 / 线路 / 通道并返回命中(**不动视角**:要不要聚焦由调用方自己调 `focusOn`),见「搜索与定位」 |
|
|
40
40
|
| `searchAsync(keyword \| options)` | 同一份口径的异步版:数据量大时把扫描放进 Worker(10 万点 / 10 万线下同步要占主线程 40 ms 上下的那一段),返回 `Promise<GisViewSearchResult>`;结果带 `worker` 与 `stale` 两个字段,见「异步搜索」 |
|
|
41
41
|
| `setCamera(camera)` / `getCamera()` | 读写 `{ center, scale }` |
|
|
42
|
-
| `getZoomBaseScale()` / `setZoomBaseScale(scale?)` | 读 / 重定**缩放联动的基准比例**(缺省是首次适应视图时的比例):不传参数就取当下相机的比例 ——
|
|
42
|
+
| `getZoomBaseScale()` / `setZoomBaseScale(scale?)` | 读 / 重定**缩放联动的基准比例**(缺省是首次适应视图时的比例):不传参数就取当下相机的比例 —— 把现在这一屏当成「原样大小」,之后放大缩小都从它算倍数;配合 `pointZoomScale` / `lineZoomScale` 使用 |
|
|
43
43
|
| `getBounds()` | 数据范围(没有点时回退到背景 GeoJSON 的 `rawBounds`,也就是 `aspectScale` 之前的真实经纬度范围) |
|
|
44
44
|
| `getViewRect()` | 当前可视范围的世界坐标矩形;自建缩略图 / 坐标读数用它换算视口框,内置鹰眼图见「鹰眼图」 |
|
|
45
45
|
| `getMinimapZoom()` / `setMinimapZoom(zoom)` / `zoomMinimapBy(factor, origin?)` | 读 / 写鹰眼图自身的倍数:`set` 夹在 `minimap.minZoom` ~ `maxZoom` 之间,`zoomMinimapBy` 以画布 CSS 像素 `origin` 为锚点缩放(缺省小图中心),没配 `minimap` 时是空操作 |
|
|
@@ -47,6 +47,8 @@
|
|
|
47
47
|
| `getLine(ref)` | 取一条线路:拾取载荷 + `path` / `bounds` / `color` / `width`(与 `listLines()` 的一项同一份口径),通道回线还带 `channelId` / `groupId` / `channelIndex`;找不到返回 `null` |
|
|
48
48
|
| `getChannel(ref)` | 取一条通道:数据那一份(`index` / `item` / `id`)+ 成员表(`lineIndexes` / `skeleton` / `offsets` / `paths`)+ 分组上下文 `context`(几组 / 当前哪组 / 每组拐点数)、`from` / `to` / `anchored` / `spacing`;找不到返回 `null` |
|
|
49
49
|
| `listPoints(options?)` | 按条件列节点快照 `{ index, item, x, y, radius, layerRank, screen? }`:选项见 `GisViewListOptions`(`indexes` / `inView` / `limit` / `withScreen` / `visibleOnly`),可见判定与 `isPointVisible` 是同一份 |
|
|
50
|
+
| `getClusters()` | 当前点聚合的展示组 `GisViewCluster[]`:按数据顺序返回,含 `count: 1` 的单成员与 `count > 1` 的聚合圆;每项带 `id` / `pointIndexes` / `pointIds` / 世界坐标 `coordinate` / 当前屏幕坐标 `screen` / 半径 `radius` / 包围盒 `bounds`。原始 `points` 与 `getData()` 不变,聚合关掉时返回空表 |
|
|
51
|
+
| `getPointCluster()` | 当前点聚合配置的归一化读数 `GisViewPointClusterReadout \| null`:`{ enabled, radius, minPoints, maxZoom, active }`,`active` 说明当前缩放档是否仍在聚合(超过 `maxZoom` 后为 `false`);引擎未就绪时为 `null` |
|
|
50
52
|
| `listLines(options?)` | 按条件列线路快照 `{ index, item, path, bounds, color, width, channelId?, groupId?, channelIndex?, screen? }`:选项与 `listPoints` 同一套;通道回线给的是骨架推导出来的那条折线(跟图上画的一致) |
|
|
51
53
|
| `getLineChannel(ref)` | 这条线路属于哪条通道:`getLineChannel('line-a')`(id)/ `getLineChannel(12)`(`lines` 下标)给 `{ lineIndex, channelId, channelIndex, channel, groupId, group }`,不在通道里返回 `null`。点了一条回线想知道它归哪条通道 / 哪一组时用它,不必自己扫通道定义 |
|
|
52
54
|
| `getElementBounds(keys)` | 一批要素 `GisViewFeatureKey[]`(`{ type: 'point' \| 'line', index }`,`getSelections()` 的结果可以直接传)的世界包围盒 `{ minX, minY, maxX, maxY }`;一个都没对上返回 `null`(数据已经换过) |
|
|
@@ -68,11 +70,13 @@
|
|
|
68
70
|
| `hoverAt(clientX, clientY)` / `clearHover()` / `getHover()` | 程序化悬停:`hoverAt` 让指针「停」到某个客户端坐标上(悬停高亮、光标与 `onHover` 一起更新,返回与 `onHover` 载荷同一份读数,空白处 `null`;不走悬停阈值,也不用先订阅事件)、`clearHover()` 撤掉并补发一条 `onHover(null)`、`getHover()` 随时读当前这一份 —— 外部列表 / 表格 hover 到某一行时联动高亮图上的要素用它 |
|
|
69
71
|
| `getFeaturesInRect(rect)` | 画布 CSS 像素矩形里有什么(与框选 / `selectInBox` 同一套坐标与判定):返回 `{ rect, worldRect, points, lines }` —— `points` 是框内的节点(与 `onSelect` 的 `items` 同一口径)、`lines` 是包围盒沾到框的线路(与 `listLines` 同一份)、`worldRect` 是这块像素对应的世界坐标范围;只读,不改选中也不画框 |
|
|
70
72
|
| `getChannelsInView()` | 当前视口里有哪几条通道(同一通道的几回线只算一条):每条给 `{ channelId, channelIndex, channel, lineIndexes, groupIds }`,侧边栏「画面里的通道」、按视口统计用它 |
|
|
71
|
-
| `selectFeatures(refs, options?)` | 接口选中(换一份选中集;`selectFeatures(null)` / 空数组就是清空):`refs`
|
|
73
|
+
| `selectFeatures(refs, options?)` | 接口选中(换一份选中集;`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'`,见「接口选中(selectFeatures)与读回选中」 |
|
|
74
|
+
| `selectWaypoint(lineRef, pathIndex?, options?)` | 代码选中一个拐点:`selectWaypoint('line-1', 2)` / `{ lineIndex, pathIndex }` / `{ lineId, pathIndex }`,并同时选中所在线路;有效下标从 `getWaypoints()` 取。传 `null` 只取消拐点选中、不改要素选中集,见「代码选中拐点(selectWaypoint)」 |
|
|
72
75
|
| `deselect(refs?)` | 取消选中:写法与 `selectFeatures` 完全一样,把这些从当前选中集里去掉、其余选中原样留着;不传 / `null` 等于取消全部(也就是 `selectFeatures(null)`),空数组是「没有目标」什么都不做,见「取消选中(deselect / selectFeatures(null))」 |
|
|
73
76
|
| `getSelections()` | 读回选中结果 `[{ type, index, item, … }]`(按选中顺序):要 id 列表 / 个数 / 包围盒看 `getSelectionData()` |
|
|
74
77
|
| `isSelected(ref)` | 这个要素在不在当前选中集里:`isSelected('node-0')`(id)/ `isSelected({ type: 'line', index: 12 })`(也可以只写下标,按 id 认不出来时当下标),返回 `true` / `false`。面板上高亮「当前这一行」时不必自己比对 `getSelections()`;选中集变化时缓存一份键集合(见「接口选中」),十万级选中下这一问也是常数级 |
|
|
75
78
|
| `getSelectionData()` | 选中集一次取全:读数(`ids` / `count` / `pointCount` / `lineCount` / `channelCount`)加要素本身(`points` / `lines` / `channels`(按通道去重,与 `getData()` 同一批对象)),另有 `items`(与 `getSelections()` 同一份)、`pointIndexes` / `lineIndexes` 与 `bounds`(世界包围盒,空选中时 `null`),见「接口选中(selectFeatures)与读回选中」 |
|
|
79
|
+
| `getCascadeHighlight()` | 当前点击级联高亮的读数:`{ origin, scope, points, lines, pointIndexes, lineIndexes }`;没有高亮或 `cascadeHighlight` 关着时返回 `null`。它只读、不改选中集,见「点击级联高亮」 |
|
|
76
80
|
| `selectInBox(box, options?)` | 按画布 CSS 像素矩形框选,等价于 Shift + 拖动(跟随 `shortcuts.boxSelect`);`options.selectionKinds` 可只覆盖这一次的节点 / 线路 / 通道类型过滤 |
|
|
77
81
|
| `beginCopyPoint(options?)` | 开始复制一个节点:给 `id` / `index` 直接出预览(`commit: true` 出预览即落地,`follow: true` 跟随鼠标,`autoCommit: false` 停在预览态),不给来源就是「先点按钮再选节点」模式,见「节点复制」 |
|
|
78
82
|
| `commitPointCopy()` / `cancelPointCopy()` | 落地 / 取消预览中的复制(返回 `end` / `cancel` 载荷) |
|
|
@@ -92,7 +96,7 @@
|
|
|
92
96
|
| `cancelRemove()` | 取消这次删除(与 Esc 同一条路):数据一个字节都不动,返回取消掉的那份载荷(`invalidated: true` 表示请求因为数据变过而作废) |
|
|
93
97
|
| `removeSelected(options?)` | 移除**当前选中的那一批**(工具栏「删除选中」同一条路):选中的节点连同绑在它们身上的线路一起删、剩下的选中回线也删掉,删完清空选中;返回 `{ ok, reason, pointIndexes, lineIndexes, pointIds, lineIds, points, lines, removedChannels }`(`lineIds` 里也含「因为节点被删而连带走掉」的线路),没有选中东西时 `ok: false` 并带回原因。一次调用只落一条历史、只发一条 `removeSelected` 数据变更 |
|
|
94
98
|
|
|
95
|
-
| `exportImage(options?)` | 导出当前画面(含标签)为图片,返回 data URL
|
|
99
|
+
| `exportImage(options?)` | 导出当前画面(含标签)为图片,返回 data URL;`scope: 'viewport'`(缺省)导当前视口、`'all'` 临时适应全部可见内容,另有 `padding` / `type` / `quality` / `scale` / `background` / `includeLabels` / `download`,见「导出图片」 |
|
|
96
100
|
| `exportSelection(options?)` | 把选中的节点(可选带上两端都在集合里的线路)单独导成图片 / 数据:`points` 不给就用选中集,`withLines` / `format` / `padding` 见「导出选中的节点」;返回 `{ ok, reason, points, lines, counts, box, pointIndexes, lineIndexes, image }`,出图时临时藏起别的要素与相机、出完还原 |
|
|
97
101
|
| `exportData(options?)` | **统一导出入口**:`scope` 选范围(`'all'` 缺省 / `'viewport'` / `'selection'`,也认 `visible` / `view` / `selected`),`parts` 选分项,`format` 选口径。`format: 'view'`(缺省)给 `{ points, lines, channels, parallelGroups }`、`'new'` 给 new.json 口径、`'test'` 给 test.json 口径、`'input'` 给与 `createGisView` 入参同构的回灌口径、`'full'` 给标准文档;`format` 也可以是注册过的自定义名字。`points` / `lines` / `channels` 可以只要一部分,解不出的引用进 `warnings`,`format` 写错(或没注册)抛异常,见「导出数据」与「自定义导出格式」 |
|
|
98
102
|
| `snapshotScene(options?)` | 当前画面的矢量快照(屏幕坐标的线 / 点 / 标签 / 背景 / 网格):`{ width, height, background, backgroundImage, grid, regions, lines, points, backgroundPoints, decorations, waypoints, raised, labels }`,`options.background: false` 丢背景、`options.backgroundColor` 只换底色、`options.labels` 原样带进去,见「导出图片」 |
|
|
@@ -119,7 +123,7 @@
|
|
|
119
123
|
| `addChannelGroupWaypoint(channelId, groupId?, coordinate?)` | 给某个分组加拐点、把这一组单独拉走:不给坐标就按默认位置放一个(第 n 组沿法线往外让 n 档),其余分组一根拐点都不动,见「分组拐点」 |
|
|
120
124
|
| `removeChannelGroupWaypoint(channelId, groupId?, pathIndex?)` | 删掉某个分组的拐点(缺省删最后一个) |
|
|
121
125
|
| `runChannelAction(actionId, options?)` | 执行右键交互框里的动作:`select-group` / `deselect-group` / `add-waypoint` / `remove-waypoint` / `split` / `merge`(`options` 带 `channelId` / `groupId` / `coordinate` / `pathIndex` / `size`),返回执行之后的上下文 |
|
|
122
|
-
| `beginAddChannel(options?)` |
|
|
126
|
+
| `beginAddChannel(options?)` | 进入「新增通道」:缺省点两个节点选起点 / 终点,或由 `options.from` 预指定起点、只需再点终点;`options` 还支持 `kind`(`'channel'` 新建通道 / `'line'` 新建独立线路,缺省 `'channel'`)/ `circuits`(一次加几条,缺省 1)/ `autoCommit` / `continuous` / `chain` / `name` / `lineId` / `id` / `lineProps` / `linePropsByMember` / `lineItems`(第二段,连同线路一起新建)/ `routing`(`'straight'` / `'orthogonal'`)/ `path`(中间拐点)/ `channelProps` / `channelDraftStyle`(本次草稿的预览样式)/ `handoff`(交接模式:ready 发完收起草稿,自己调 `addChannel` 落地)/ `select`(点中的节点顺手选中)/ `originalEvent`,见「新增通道」 |
|
|
123
127
|
| `getAddChannelDraft()` | 当前新增通道草稿(两个节点的信息与可选方案),没有草稿时为 `null` |
|
|
124
128
|
| `updateAddChannelStyle(patch?)` | 字段级合并当前草稿的预览样式(`color` / `width` / `dot` / `dotColor` / `arrow` / `arrowSize` / `arrowPositions` / `arrowReverse` / `arrowColor` / `circuitSpacing` / `opacity` / `customDraw`);传 `null` 回到全局 `channelDraftStyle`,没有草稿时什么也不做 |
|
|
125
129
|
| `continueAddChannel(options?)` | 开下一段草稿:连续模式落地时内部自动调(发 `phase: 'restart'`),也可以手动调;草稿已经退出时按 `options` 重新进来 |
|
|
@@ -188,7 +192,7 @@
|
|
|
188
192
|
|
|
189
193
|
返回 `this` 的方法都可以链式调用;返回其它值的方法(`get*` / `list*` / `export*` / `search` / `pick*` / `add*` / `remove*` / `copy*` / `merge*` / `locate*` 这些)在下面的「参数速查」里都标了返回类型。
|
|
190
194
|
|
|
191
|
-
**怎么确认「组件到底有哪些属性和方法」**:上面那张表按功能分组介绍,下面的「参数速查」把实例的**每个成员逐个列全**(当前
|
|
195
|
+
**怎么确认「组件到底有哪些属性和方法」**:上面那张表按功能分组介绍,下面的「参数速查」把实例的**每个成员逐个列全**(当前 253 个:250 个方法 + `el` / `canvas` / `gl` 三个属性),`options` 表列全 95 个键,数据字段表列全 249 个字段。这三份清单不靠手抄 —— 它们直接对着源码与类型对账:
|
|
192
196
|
|
|
193
197
|
- `node docs/steps/gen-api-index.mjs`:从 `create.js` 的实例定义、本文档的两张表与 `types.d.ts` 生成 `docs/demos/api-index.js`(`API_SUMMARY` / `API_SECTIONS` / `API_OPTIONS`),demo 的「实例 API」面板读的就是它;带 `--check` 时只校验有没有过期。
|
|
194
198
|
- `node docs/steps/check-doc-coverage.mjs`:10 项双向对账 —— 实例成员 × 文档 / × 参数速查 / × 类型、参数速查与实例方法主表各自反查过期条目、类型反查过期声明、数据字段 × 文档、options 键 × 文档 / options 表反查过期字段、demo 清单是否最新。加一个实例成员、改一个 options 键而没同步文档时,这个脚本会直接报出来。
|
|
@@ -196,4 +200,6 @@
|
|
|
196
200
|
|
|
197
201
|
---
|
|
198
202
|
|
|
203
|
+
**相关章节**:[08 选中与拐点](08-选中与拐点.md) · [17 参数速查(逐个方法)](17-参数速查.md) · [18 逐方法示例(复制就能跑)](18-逐方法示例.md)
|
|
204
|
+
|
|
199
205
|
[← 15 导出与集成](15-导出与集成.md) · [手册目录](../GisView.md) · [17 参数速查(逐个方法) →](17-参数速查.md)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 17 参数速查(逐个方法)
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 253 个成员逐个列全:参数、默认值与返回。
|
|
4
4
|
|
|
5
5
|
### 参数速查(逐个方法)
|
|
6
6
|
|
|
@@ -8,6 +8,17 @@
|
|
|
8
8
|
不写默认值的就是必填;返回值只写类型(`this` = 实例本身,可以接着链式调),对象型返回值的字段名见 `src/gis-view/types.d.ts` 里同名的接口。
|
|
9
9
|
消息里的每个名字都能在下面查到 —— `node docs/steps/check-doc-coverage.mjs` 会逐个对账(实例成员 + 数据字段全覆盖才算通过)。
|
|
10
10
|
|
|
11
|
+
#### 调用与响应口径(先读这一段)
|
|
12
|
+
|
|
13
|
+
参数表只列出「最少要知道的东西」,实际调用时这几种响应在所有成员上口径一致:
|
|
14
|
+
|
|
15
|
+
- **同步方法返回 `this` 时可链式调用**:所有 `update*` / `set*` / `add*` / `remove*`、选中与视角方法都先完成本地状态更新再返回实例;需要结果时用相邻的 `get*` / `list*` 读回。少数返回数组、对象或 `null` 的方法在「返回」列单独标出。
|
|
16
|
+
- **数据写入只发一次通知**:`updatePoint`、`updateLine`、`patch*`、`add*`、`remove*` 等每次成功改数据都会发一条对应的 `dataChange`(底层统一为 `updatePoints` / `updateLines` / `updateChannels` 等类型)并落一步历史;在 `batch()` 里连续调用会合并成一条。`emit: false` 只写数据、不发通知,适合宿主自己在保存成功后统一刷新。
|
|
17
|
+
- **选中方法会同步选中集**:`selectFeatures` / `selectWaypoint` / `selectInBox` 先更新引擎选中态,再同步 `getSelections()`、`getSelectionData()` 与 `isSelected()`;一次有效变更会发 `onSelect`(`cause` 标明是 `api`、`box` 或指针来源)和 `onSelectChange`。没有命中任何目标时不会凭空选中,`selectWaypoint(null)` 只清拐点、不动要素选中集。
|
|
18
|
+
- **视角方法会更新相机**:`focusOn` / `zoomTo` / `setCamera` / `fitView` 成功落到目标范围后更新 `getCamera()`,并触发 `onCameraChange`;目标认不出来、视口尚未量出或参数非法时保持当前相机。`focusOn` 的 `scale` / `center` / `padding` / `maxZoom` 只影响这一次调用,不会改写持久配置。
|
|
19
|
+
- **只读方法返回快照或副本**:`getSelectionData()`、`getFilter()`、`getStats()`、`snapshotScene()`、`listPoints()` / `listLines()` 返回的是调用当时的读数,不会随后续数据变更自动更新;需要最新值就再调一次。对象型字段的含义以 `types.d.ts` 同名接口为准。
|
|
20
|
+
- **失败是可控的**:找不到 id / 下标越界 / 不支持的写法会跳过这一条,能返回 `null` 或 `{ ok: false, reason }` 的就按对应签名返回;需要排查时订阅 `onWarning`。异步筛选 / 搜索通过完成事件、`getFilterResult()` / 搜索结果或返回的 Promise 取结果,不要在调用下一行假定 Worker 已经跑完。
|
|
21
|
+
|
|
11
22
|
#### 配置与数据
|
|
12
23
|
|
|
13
24
|
| 方法 | 参数(名字: 类型 = 默认值) | 返回 |
|
|
@@ -47,12 +58,12 @@
|
|
|
47
58
|
| `zoomBy(factor, origin?)` | `factor: number` 缩放倍数(`> 1` 放大、`< 1` 缩小);`origin?: [number, number]` 缩放中心(画布 CSS 像素,缺省画布中心) | `this` |
|
|
48
59
|
| `zoomTo(scale, origin?)` | `scale: number` 目标缩放值(世界单位 → CSS 像素的比例);`origin?: [x, y]` 缩放中心 | `this` |
|
|
49
60
|
| `zoomToBounds(bounds, padding?)` | `bounds: GisViewBounds` 要装进画面的世界矩形 `[minX, minY, maxX, maxY]`(也认 `{ minX, minY, maxX, maxY }`);`padding?: number` 四周留白 | `this` |
|
|
50
|
-
| `focusOn(target, options?)` | `target: GisViewFocusTargets` 要对准的东西:id / `{ type, index }` / `[x, y]` 坐标 /
|
|
61
|
+
| `focusOn(target, options?)` | `target: GisViewFocusTargets` 要对准的东西:id / `{ type: 'point' \| 'line' \| 'channel' \| 'group', id \| index }` / `{ channelId }`(整条通道)/ `{ type: 'group', channelId?, groupId }` / `[x, y]` 坐标 / 矩形 / `{ lngLat }` / `{ center }`,或者**一批**(数组取整体包围盒)。字符串按「先节点、再线路」,裸字符串不能表示通道;同 id 用显式 `type` 消歧,分组必须用 `type: 'group'`(`groupId` 全局唯一时可省略 `channelId`)。四种显式类型共用同一套包围盒适配,没有额外放大倍率;`maxZoom` 只给单点 / 单线这类零面积目标补最小范围。`options?: GisViewFocusOptions`:`scale` 直接给比例、`center: true` 只居中且不动比例、`padding` 要四周留白(CSS 像素,缺省 40)、`maxZoom` 限制这次适配的最大比例、`select` 顺带选中(`true` 选这次目标,也可另给一批写法)、`mode` 决定怎么并进当前选中集。目标认不出来或参数非法时什么都不做 | `this`(相机更新后发 `onCameraChange`;`select` 生效时另发 `onSelect` / `onSelectChange`) |
|
|
51
62
|
| `search(input)` | `input: string \| GisViewSearchOptions` 关键字,或 `{ keyword, scope, fields, limit }` 这类选项(`scope` 可选 `'points'` / `'lines'` / `'channels'`,也认它们的数组)—— **只返回结果、不动视角**,要定位就自己调 `focusOn(result.hits, …)` | `GisViewSearchResult` |
|
|
52
63
|
| `searchAsync(input)` | 同上 | `Promise<GisViewSearchResult>`:多一个 `worker`(是不是在 Worker 里算的)与 `stale`(回来时数据已经改过、或又搜过一次,这一份不作数了) |
|
|
53
64
|
| `setCamera(camera)` | `camera: Partial<GisViewCamera>` 要改的相机字段 `{ x, y, scale }`(只写一个也行) | `this` |
|
|
54
65
|
| `getCamera()` | 无 | `GisViewCamera` |
|
|
55
|
-
| `getZoomBaseScale()` | 无 | `number` 缩放联动的基准比例(`pointZoomScale` / `lineZoomScale`
|
|
66
|
+
| `getZoomBaseScale()` | 无 | `number` 缩放联动的基准比例(`pointZoomScale` / `lineZoomScale` 共用那一份;缺省是首次适应视图时的 `camera.scale`) |
|
|
56
67
|
| `setZoomBaseScale(scale?)` | `scale?: number` 新的基准比例;不传取当下相机的比例(把现在这一屏当成「原样大小」) | `this` |
|
|
57
68
|
| `getBounds()` | 无 | `GisViewBounds` |
|
|
58
69
|
| `getViewport()` | 无 | `{ cssWidth, cssHeight, pixelRatio, displayScale }`:画布 CSS 尺寸、设备像素比与渲染分辨率比例 |
|
|
@@ -106,6 +117,8 @@
|
|
|
106
117
|
| `getLine(ref)` | `ref` 线路定位(同上) | `GisViewLineInfo \| null` |
|
|
107
118
|
| `getChannel(ref)` | `ref` 通道定位:通道 id 或下标 | `GisViewChannelSnapshot \| null` |
|
|
108
119
|
| `listPoints(options?)` | `options?: GisViewListOptions`:`indexes`(只看这几个下标)、`inView: boolean`(只要当前视口里的)、`withScreen: boolean`(连屏幕坐标一起给)、`visibleOnly: boolean`(跳过隐藏的)、`limit: number`(最多几条) | `GisViewListedPoint[]` |
|
|
120
|
+
| `getClusters()` | 无 | `GisViewCluster[]`。当前展示组(含 `count: 1` 的单成员),`screen` 按当前相机现算;聚合关掉时是空表 |
|
|
121
|
+
| `getPointCluster()` | 无 | `GisViewPointClusterReadout \| null`。归一化配置 `{ enabled, radius, minPoints, maxZoom, active }`,超过 `maxZoom` 后 `active` 为 `false` |
|
|
109
122
|
| `listLines(options?)` | 同 `listPoints`(`inView` / `withScreen` / `limit`…) | `GisViewListedLine[]` |
|
|
110
123
|
| `forEachPointInView(rect, visit)` | `rect: GisViewBounds` 世界坐标矩形(一般直接给 `getViewRect()` 的返回值);`visit: (index, item, x, y, radius) => void \| false` 逐个回调,返回 `false` 提前结束 | `void`。只遍历矩形里的可见节点(数据顺序、不建中间数组):与 `listPoints({ inView: true })` 同一份可见判定,但不生成清单 —— 放大看一小片时不会去碰整份数据 |
|
|
111
124
|
| `getVisibleData()` | 无 | `GisViewData` |
|
|
@@ -126,16 +139,18 @@
|
|
|
126
139
|
|
|
127
140
|
| 方法 | 参数(名字: 类型 = 默认值) | 返回 |
|
|
128
141
|
| --- | --- | --- |
|
|
129
|
-
| `selectFeatures(refs, options = {})` | `refs: GisViewSelectionRefs`
|
|
142
|
+
| `selectFeatures(refs, options = {})` | `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'` 去掉 | `this`(选中真的变了才发 `onSelect` 与 `onSelectChange`,`cause` 为 `api`) |
|
|
143
|
+
| `selectWaypoint(lineRef, pathIndex?, options = {})` | `lineRef` 线路 id、`lines` 下标或 `{ lineIndex, pathIndex }` / `{ lineId, pathIndex }` 对象;`pathIndex?: number` 必须是 `getWaypoints()` 给出的可编辑中间拐点下标(首尾端点不算,通常直接从读数里取);`options?: GisViewSelectOptions` 的 `mode` 决定所在线路怎么并进当前选中集(缺省 `replace`)。有效拐点会同时选中线路;线路不存在 / 下标非法 / 拐点不可见时只清拐点选中,不猜位置;传 `null` 也只清拐点,不改要素选中集 | `this` |
|
|
130
144
|
| `deselect(refs = null)` | `refs?: GisViewSelectionRefs` 要取消的东西(写法与 `selectFeatures` 一致:节点 / 通道 / 线路 / 混合一批);不传 / `null` 等于取消全部(= `selectFeatures(null)`),空数组是「没有目标」什么都不做 | `this` |
|
|
131
145
|
| `getSelections()` | 无 | `GisViewPickResult[]` |
|
|
132
146
|
| `isSelected(ref)` | `ref: GisViewFeatureRef \| GisViewFeatureKey \| GisViewSelectionRefObject` 要素定位(id / 下标 / `{ id }` / `{ index }` / `{ type, index }` / `{ item }`) | `boolean` |
|
|
133
147
|
| `getSelectionData()` | 无 | `GisViewSelectionData`:`{ ids, count, pointCount, lineCount, channelCount, points, lines, channels, items, pointIndexes, lineIndexes, bounds }`(`bounds` 是世界包围盒,空选中时 `null`) |
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
148
|
+
| `getCascadeHighlight()` | 无 | `GisViewCascadeHighlightInfo \| null`:当前点击级联高亮的来源、范围与节点 / 线路读数 `{ origin, scope, points, lines, pointIndexes, lineIndexes }`,不改变选中集 |
|
|
149
|
+
| `selectInBox(box, options = {})` | `box: GisViewRect` **画布 CSS 像素**矩形 `{ x, y, width, height }`(与手动框选同一套坐标);`options?: GisViewSelectInBoxOptions`:`selectionKinds` 临时覆盖这一次保留哪几类(`'point'` / `'line'` / `'channel'`、数组、`'all'` / `true` / `false` / `null`,不写沿用全局 `selectionKinds`),`originalEvent` 原样带进 `onSelect`;第二段也兼容旧的 Event 写法。空框不会选中任何要素 | `this`(发 `onSelect` / `onSelectChange`,`cause` 为框选) |
|
|
150
|
+
| `beginCopyPoint(options = {})` | `options: GisViewCopyStartOptions`:`id` / `index` / `item` 三选一给来源,都不给就进入「下一次点选节点」模式;`coordinate` / `screen` 是落点(缺省按 `copy.offset`);`follow` 让预览跟指针;`autoCommit` 覆盖 `copy.autoCommit`;`commit: true` 出预览即落地;`via` / `originalEvent` 原样带回。必须配置 `copy`(`enabled` 不为 `false`),否则返回 `null`。预览节点插在 `points` 末尾且不带 id,不会把绑定源 id 的线路 / 通道带过去 | `GisViewPointCopyPayload \| null`:`phase: 'start'` 的预览载荷;来源认不出来时返回 `null` |
|
|
151
|
+
| `commitPointCopy()` | 无:把当前复制预览落地,先发 `commit`、落地后发 `end`;`commit` 阶段载荷里的 `cancel()` 可以拦住这次复制 | `GisViewPointCopyPayload \| null`:成功的 `end` 载荷;没有预览或已被取消时为 `null` |
|
|
152
|
+
| `cancelPointCopy()` | 无:撤掉预览并补一条 `cancel`,数据与历史不动 | `GisViewPointCopyPayload \| null`:取消载荷;没有预览时为 `null` |
|
|
153
|
+
| `updateCopyPoint(patch)` | `patch: Partial<GisViewPoint>` 预览节点的字段级合并(名称 / 样式等;`x` / `y` 仍以当前落点为准),只重解析这一个预览节点 | `GisViewPoint \| null`:改完的预览节点;没有预览或 `patch` 不是对象时 `null` |
|
|
139
154
|
| `getPointCopy()` | 无 | `GisViewPointCopyState \| null` |
|
|
140
155
|
| `copyPoint(source?)` | `source?: string \| number \| GisViewCopyStartOptions` 复制哪个节点(不给就用选中的 / 光标下的,都没有就进「点一个节点」模式) | `GisViewCopyItem \| null` |
|
|
141
156
|
| `copyPoints(sources?, options = {})` | `sources?: GisViewPointRef \| GisViewPointRef[]` 要复制的节点(不给就取当前选中集;`copySelectedPoints` 不回落到光标);显式给 `sources` 时只复制这批节点,不再顺带选中的线路 / 通道。`options: GisViewCopyPointsOptions`:`coordinate` / `screen`(落点,缺省按 `copy.offset`)、`offset`(屏幕像素偏移)、`lineIndexes` / `channelIndexes`(显式点名选中的线路 / 通道)、`withLines` / `withChannels`(缺省 `false`:只复制选中要素;写 `true` 恢复「来源内部全带」的旧口径,写 `false` 连选中线路 / 通道也不带)、`select`(复制后选中新节点)、`label` / `via` / `originalEvent` | `GisViewBatchCopyPayload` |
|
|
@@ -150,14 +165,14 @@
|
|
|
150
165
|
| `splitPoint(source, parts, options = {})` | `source: GisViewPointRef` 要拆的节点;`parts: GisViewSplitPointPart[]` 至少两份,每份可直接写节点字段或放进 `item`,并用 `lines` / `channels` / `channelFrom` / `channelTo` 分配线路与通道端点;`options?: GisViewSplitPointOptions`:`keepSourceId`(缺省 `true`,第一份沿用来源 id)/ `label` | `GisViewSplitPointOutcome`:`{ ok, reason, source, items, indexes, pointIds, linesChanged, removedLines, removedLineIds, removedLineIndexes, channelsChanged, removedChannels, removedChannelIds, skipped, changes }`;`changes` 可直接作为后端事务输入 |
|
|
151
166
|
| `getPointMerge()` | 无(载荷带 `impact`:`lineCount` / `linesChanged` / `removedLines` / `lineIds` / `removedLineIds` 与通道读数,确认前就能估算影响) | `GisViewPointMergePayload \| null` |
|
|
152
167
|
| `resolvePointMerge(confirmed, options = {})` | `confirmed?: boolean`(缺省 `true` = 确认,`false` = 取消);`options?: GisViewPointMergeConfirmOptions`:`keep` 选 `'target'`(缺省,保留碰撞目标)/ `'source'`(保留拖动的来源),`item` 是最终节点字段补丁(名称 / 分区 / 颜色 / 尺寸 / 图标 / 描边等;位置与 id 始终取保留端) | `GisViewPointMergePayload \| null` |
|
|
153
|
-
| `commitPointMerge()` |
|
|
154
|
-
| `revertPointMerge(options = {})` | `options?: { originalEvent?: Event \| null; silent?: boolean }
|
|
168
|
+
| `commitPointMerge()` | 无:收掉「已确认、数据已由使用方并好」的合并状态;`mergePoints` / `resolvePointMerge` 的正常路径由组件自己调用,只有完全自建合并落地流程时才手动调 | `boolean`:真的收掉了一个待确认合并为 `true`,没有可收的状态为 `false` |
|
|
169
|
+
| `revertPointMerge(options = {})` | `options?: { originalEvent?: Event \| null; silent?: boolean }`:把拖动的来源节点还原回原位并收掉合并状态;`silent: true` 时不补发 `cancel` 载荷 | `GisViewPointMergePayload \| null`:回退载荷;没有待回退的合并时为 `null` |
|
|
155
170
|
| `removePoints(refs, options = {})` | `refs: \| GisViewFeatureRef \| 数组 \| 'all' \| 'selection' \| 'visible'` 要删哪些节点;`options?: { reason?: string }` 记进事件载荷的删除原因 | `GisViewRemovePointsOutcome` |
|
|
156
|
-
| `removeSelected(options = {})` | `options?: { reason?: string }`
|
|
157
|
-
| `requestRemove(options = {})` | `options?: { originalEvent?: Event \| null }` 原样带进载荷(键盘触发时是那一次 `keydown
|
|
158
|
-
| `getRemoveRequest()` |
|
|
159
|
-
| `resolveRemove(scope)` | `scope?: GisViewRemoveScope` 删除范围(缺省用载荷里的 `scope`) | `GisViewRemoveResult \| null` |
|
|
160
|
-
| `cancelRemove()` |
|
|
171
|
+
| `removeSelected(options = {})` | `options?: { reason?: string }` 记进删除载荷:直接删当前选中集(节点连带线路 / 空掉的通道,拐点先删),删完清空选中;整次调用只落一条历史、只发一条 `removeSelected` 数据变更 | `GisViewRemoveSelectedOutcome`:`{ ok, reason?, pointIndexes, lineIndexes, pointIds, lineIds, points, lines, removedChannels }`;没有选中可删时为 `ok: false` |
|
|
172
|
+
| `requestRemove(options = {})` | `options?: { originalEvent?: Event \| null }` 原样带进载荷(键盘触发时是那一次 `keydown`):只生成待确认载荷,**数据不动**;`remove.confirm` 为 `false` 时当场删,为函数时按返回值 / Promise 裁决,不写就停在 `pending` | `GisViewRemoveOutcome`:`phase: 'pending' \| 'remove' \| 'cancel'` 的载荷,或没有可删要素时的 `phase: 'empty'` 失败读数 |
|
|
173
|
+
| `getRemoveRequest()` | 无:读当前待确认的删除请求,供自建确认框渲染 | `GisViewRemovePayload \| null`:没有待确认请求时为 `null` |
|
|
174
|
+
| `resolveRemove(scope)` | `scope?: GisViewRemoveScope` 删除范围(缺省用载荷里的 `scope`;可选 `'lines'` / `'groups'` / `'channels'`) | `GisViewRemoveResult \| null`:删除结果;没有待确认请求或请求已裁决时为 `null` |
|
|
175
|
+
| `cancelRemove()` | 无:取消待确认删除,数据不动并补 `cancel` 载荷 | `GisViewRemovePayload \| null`:取消载荷;没有待确认请求时为 `null` |
|
|
161
176
|
|
|
162
177
|
#### 拐点与通道
|
|
163
178
|
|
|
@@ -186,7 +201,7 @@
|
|
|
186
201
|
| `addChannelGroupWaypoint(channelId, groupId, coordinate)` | `channelId` 通道 id;`groupId` 分组 id;`coordinate` 新拐点世界坐标 | `this` |
|
|
187
202
|
| `removeChannelGroupWaypoint(channelId, groupId, pathIndex)` | `channelId` / `groupId` / `pathIndex` 要删的骨架顶点下标 | `this` |
|
|
188
203
|
| `runChannelAction(actionId, options?)` | `actionId: GisViewChannelActionId` 动作名(`'select-group'` / `'deselect-group'` / `'add-waypoint'` / `'remove-waypoint'` / `'split'` / `'merge'`,见 `getChannelContext().actions`);`options?: GisViewChannelActionOptions` 动作自己的参数(`groupId` / `lineId` / `coordinate`…) | `GisViewChannelContext \| null` |
|
|
189
|
-
| `beginAddChannel(options = {})` | `options?: GisViewChannelDraftOptions` 草稿配置:`kind` / `circuits` / `autoCommit` / `continuous` / `chain` / `name` / `lineId` / `lineProps` / `linePropsByMember` / `lineItems`(第二段)/ `routing` / `path`(中间拐点)/ `channelProps` / `channelDraftStyle`(本次草稿的预览样式)/ `handoff`(交接模式)/ `select`(点中的节点顺手选中,走 `onSelect`
|
|
204
|
+
| `beginAddChannel(options = {})` | `options?: GisViewChannelDraftOptions` 草稿配置:`from`(预指定起点,下一步只选终点)/ `kind` / `circuits` / `autoCommit` / `continuous` / `chain` / `name` / `lineId` / `id` / `lineProps` / `linePropsByMember` / `lineItems`(第二段)/ `routing` / `path`(中间拐点)/ `channelProps` / `channelDraftStyle`(本次草稿的预览样式)/ `handoff`(交接模式)/ `select`(点中的节点顺手选中,走 `onSelect` 那一套)/ `originalEvent` | `this`(只负责那条示例假通道,真正新增走 `addChannel`) |
|
|
190
205
|
| `getAddChannelDraft()` | 无 | `GisViewChannelDraftPayload \| null` |
|
|
191
206
|
| `updateAddChannelStyle(patch = {})` | `patch?: GisViewChannelDraftStyle \| null` 字段级合并的预览样式(箭头位置 / 多回线间距 / 自绘等);传 `null` 回到全局 `channelDraftStyle` | `this` |
|
|
192
207
|
| `continueAddChannel(options = {})` | `options?: GisViewChannelDraftOptions` 开下一段草稿(写法与 `beginAddChannel` 一致,不传就沿用这一段原来的) | `this` |
|
|
@@ -284,7 +299,7 @@
|
|
|
284
299
|
| 方法 | 参数(名字: 类型 = 默认值) | 返回 |
|
|
285
300
|
| --- | --- | --- |
|
|
286
301
|
| `exportData(options = {})` | `options: GisViewExportDataOptions`:`scope`(`'all'` 缺省 / `'viewport'` / `'selection'`,也认 `visible` / `view` / `selected`)、`format`(`'view'` 缺省 / `'input'` / `'new'` / `'test'` / `'full'`)、`parts`(只导 `points` / `lines` / `channels` / `parallelGroups` 里的哪几份)、`points` / `lines` / `channels`(只导指定要素)、`withLines: false`(selection 不要两端都在集合里的线路)、`labels`、`extra`。`format: 'full'` / `'input'` 返回可直接回灌的数据,不夹带 `scope` / `counts` 读数 | `GisViewExportDataResult \| GisViewDocument`(`format: 'full'`) |
|
|
287
|
-
| `exportImage(options = {})` | `options?: GisViewExportImageOptions`:`type`(`'image/png'` / `'image/jpeg'`)、`quality`(JPEG 0 ~ 1)、`scale
|
|
302
|
+
| `exportImage(options = {})` | `options?: GisViewExportImageOptions`:`type`(`'image/png'` / `'image/jpeg'` / `'image/webp'` / `'svg'`)、`quality`(JPEG / WebP 0 ~ 1)、`scale`(导出倍数;SVG 只影响宽高)、`scope`(`'viewport'` 缺省 / `'all'` 全部内容)、`padding`(`scope: 'all'` 的留白,缺省 24)、`background`(缺省带背景 / `false` 或 `'none'` 透明 / 颜色字符串换底色)、`includeLabels`(缺省 `true`)、`download`(`true` 或文件名) | `Promise<string>`(data URL) |
|
|
288
303
|
| `exportSelection(options = {})` | `options?: GisViewExportSelectionOptions`:`format` / `type` / `quality` / `scale` / `padding`(只导选中要素那一块) | `Promise<GisViewExportSelectionResult>` |
|
|
289
304
|
|
|
290
305
|
#### 筛选
|
|
@@ -300,13 +315,13 @@
|
|
|
300
315
|
| 方法 | 参数(名字: 类型 = 默认值) | 返回 |
|
|
301
316
|
| --- | --- | --- |
|
|
302
317
|
| `on(name, handler)` | `name: GisViewEventName \| '*'` 事件名(`'dataChange'` / `'labelClick'`… 或 `'*'` 订阅全部);`handler: (payload, name?) => void` 回调,载荷字段见「事件」一节的表 | `() => void` 取消订阅 |
|
|
303
|
-
| `once(name, handler)` |
|
|
304
|
-
| `off(name, handler?)` | `name`
|
|
318
|
+
| `once(name, handler)` | 与 `on` 同一套事件名与载荷;只触发一次,回调跑完自动摘掉。返回的取消函数可提前撤销;即使提前取消,重复调用也安全 | `() => void` 取消订阅 |
|
|
319
|
+
| `off(name, handler?)` | `name` 事件名(也认 `'*'`);`handler?` 只摘掉这一个回调,不传 = 摘掉这个事件的全部订阅 | `number` 摘掉几条(没摘到返回 `0`) |
|
|
305
320
|
| `use(plugin)` | `plugin: GisViewPlugin`(`(view, context) => hook`,与 `options.plugins` 的写法一致):立即执行一次,返回卸载函数 —— 调它跑插件自己的 `destroy`(重复调用只清一次,实例销毁之后也安全) | `() => void` 卸载 |
|
|
306
321
|
| `getFeatures()` | 无 | `GisViewFeatureState` |
|
|
307
322
|
| `setFeatures(next)` | `next: GisViewFeaturesInput` 预设名(`'edit'` / `'view'` / `'static'`)、开关表或布尔值 | `this` |
|
|
308
|
-
| `undo()` / `redo()` |
|
|
309
|
-
| `canUndo()` / `canRedo()` |
|
|
323
|
+
| `undo()` / `redo()` | 无:从撤销 / 重做栈回放一步;会同步数据、发 `history` 与对应的 `dataChange`,并更新相机以外的运行时读数 | `GisViewHistoryStepResult \| null`:`{ type, label, canUndo, canRedo }`;历史没开或栈空时为 `null` |
|
|
324
|
+
| `canUndo()` / `canRedo()` | 无:只读当前两份栈,不触发历史变化;界面据此灰掉按钮 | `boolean` |
|
|
310
325
|
| `getHistoryState()` | 无 | `GisViewHistoryState` |
|
|
311
326
|
| `getHistory()` | 无 | `GisViewHistoryEntry[]` |
|
|
312
327
|
| `clearHistory()` | 无 | `number` |
|
|
@@ -337,4 +352,6 @@
|
|
|
337
352
|
|
|
338
353
|
---
|
|
339
354
|
|
|
355
|
+
**相关章节**:[08 选中与拐点](08-选中与拐点.md) · [16 实例方法总表](16-实例方法总表.md) · [18 逐方法示例(复制就能跑)](18-逐方法示例.md)
|
|
356
|
+
|
|
340
357
|
[← 16 实例方法总表](16-实例方法总表.md) · [手册目录](../GisView.md) · [18 逐方法示例(复制就能跑) →](18-逐方法示例.md)
|