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
|
@@ -41,8 +41,9 @@
|
|
|
41
41
|
| `onLabelClick` / `onLabelDrag` / `onLabelContextMenu` / `onLabelDblClick` | `kind` / `index` / `id` / `labelId` / `item` / `label`(这一条标签的 id、内容、来源、合并后的样式)/ `parent`(挂在哪条要素上,线路在通道里时带通道 / 分组)/ `state` |
|
|
42
42
|
| `onQualityChange` | `{ mode, name, level, glow, ornament, scale, budgetMs, frameMs }` |
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
三个事件的总线载荷是 `{ payload, event }`(要原样带回 DOM 事件):`pointerDown` / `pointerUp` / `contextMenu`,
|
|
45
|
+
回调那一侧仍是 `(payload, event)` 两个参数,`view.on` 订阅时记得拆包;通道回线的右键上下文在同一份
|
|
46
|
+
`contextMenu` 载荷的 `channelContext` 上。
|
|
46
47
|
|
|
47
48
|
### 自建面板常用的读数
|
|
48
49
|
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
|
|
98
98
|
### 16.70 自适应比例为什么给「联动指数」留一个没写的状态、updateLine 的拐点口径怎么定、API 速查页的数据是怎么长出来的(本轮已做 / 留档)
|
|
99
99
|
|
|
100
|
-
-
|
|
100
|
+
- **缩放联动指数的历史取舍与现行口径**:`pointZoomScale` / `lineZoomScale` 现在仍以 `0` 为缺省(尺寸不跟缩放走),要跟随地图就显式写指数;原来自适应比例开关负责给「没写」的项兜底,后来确认它只是把两项指数隐式设成 `1`,无法解决远处孤立点撑大包围盒导致的节点拥挤,因此已移除。`setZoomBaseScale(scale?)` 保留:它仍走 `SCALE_ONLY_KEYS` 那条「只改尺寸」的增量路(不动几何、不重解析),基准不给参数就取当前 `camera.scale`,配合 `getZoomBaseScale()` 读回。包围盒撑大时的间距问题改由 `fitSpacing` 处理:适应视图时按可见节点最近中心距反推比例,**相机中心仍取普通适应的包围盒中心**;只有比例被提高,不再按最近节点对或节点中位数另算中心。`measurePointSpacing()` 因此只保留距离扫描,`reflowChannelWidths()` 对单组通道在宽度输入未变时直接跳过车道与折线重算,见主手册「适应视图的节点间距(fitSpacing)」。
|
|
101
101
|
- **为什么「单独改某个线路」不新开一个方法,而是把 `updateLine` 的口径写清楚**:线路能改的就三类 —— 属性(颜色 / 宽度 / 线形…)、几何(拐点)、分组归属(`groupId` / `groupIndex` / `channelId`),`updateLine(id, patch)` 本来就都收:`path` 是整条折线(含首尾两端,`[x, y]` 或 `{ x, y }`),只想改中间拐点用 `setLineWaypoints`(两端从 `from` / `to` 或 `start` / `end` 推),属性与分组指令一次下发时按「线路数据只发一条 `updateLine`、分组再发一条 `channelGroups`」走,指令本身不写进线路数据。这三条口径补进主表、参数速查与逐方法示例,自测新增三条钉住「一次下发只发一条」与「指令不进数据」。
|
|
102
102
|
- **为什么 API 速查页的数据不手写**:手写的清单一改源码就漂。数据还是同一份《GisView.md》:`docs/steps/gen-api-index.mjs` 原来就导出成员 / 分组 / options,这一轮给每条补上 `examples: [{ group, code, from }]` —— 示例来自「逐方法示例」一节,解析时按 `####` 分组、围栏切块,成员名取首行注释冒号前的标识符;首行没点名、但代码里真实出现 `view.某成员(` 的块按兜底认领。`check-doc-coverage.mjs` 因此多了一项「实例成员 × 逐方法示例」:235 个成员每个都要在示例里露面,缺一个就 FAIL(补「自定义运算符」那一段就是这个对账逼出来的)。页面(`docs/api/index.html`)自包含:左侧分组 + 搜索 + 类型开关,右侧成员卡(参数 / 返回 / 说明 / 示例 + 高亮 + 复制),底部 options 逐条列四件套;自测页通过 `__gisApi` 钩子读它的 DOM,钉住 235 张卡都有示例、86 个 options 四件套、搜索过滤与 `select(名字)` 高亮、类型开关能单独收起属性。
|
|
103
103
|
- **验证**:`npx tsc --noEmit` 0 错;十三页自测共 **1625** 条 0 FAIL(`selftest-scale.html` 95 / `selftest-features.html` 522 / `selftest-demos.html` 150 / `selftest-docs.html` 73);`npm run check:docs` 全绿;`npm run build` 通过。
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
- **选哪一对**:只要世界坐标(读落点、对账)用 `clientToWorld` / `worldToClient`;要把鼠标位置喂给只吃画布像素的接口 —— `pick` / `getContextAt` / `nearestPointsAt` / `nearestLineAt` / `getFeaturesInRect` / `selectInBox` / `setDropPreview({ screen })` / `zoomTo(scale, origin)` 的锚点 —— 先用 `clientToScreen` 转一档(世界坐标喂不进这些接口);手上已经握着画布像素(`getPointer().screen`、拾取载荷的 `screen`、`listPoints({ withScreen })`),要摆 `position: fixed` 的浮层用 `screenToClient`。两对数学上可互推(`clientToScreen` 的结果就等于 `project(clientToWorld(...))`),专名省掉绕世界坐标那一步,也与指针事件共用同一份 canvas rect 缓存 —— 组件自己的提示框跟随(`handlePointerMove`)走的也是它。
|
|
15
15
|
- **像素比**:默认取 `window.devicePixelRatio`,用 `pixelRatio` 覆盖。线宽、节点尺寸、虚线图案、光标热点都是 **CSS 像素**,在高分屏上会按像素比放大到设备像素,因此屏幕上看起来始终一样大。另外有一层画布**像素预算**(`maxCanvasPixels`,默认 400 万):全屏 / 高分屏下 CSS 面积一大,渲染倍率就按 `sqrt(预算 / CSS 面积)` 压下来 —— 填充率不随屏幕面积线性上涨(全屏 + dpr 2 曾经是窗口态的十倍像素),线宽与字号仍然是 CSS 像素,观感基本不变。
|
|
16
16
|
- **宿主缩放**:页面用 CSS `zoom`(大屏适配的常见做法:`document.body.style.zoom = innerWidth / 1920`)或祖先的 `transform: scale` 把这一层整体放大 / 缩小时,组件里的 **CSS 像素一律是布局像素** —— 线宽、节点尺寸、字号跟着页面一起变大,与旁边的 DOM 一致(不是保持设备像素大小不变)。画布备份像素按「设备像素比 × 显示比例」开,缩放之后仍然 1:1 落在设备像素上,画面不发糊。`getViewport()` 里的 `displayScale` 就是这个比例(1 表示没有缩放):自建 DOM 覆盖层时,`getBoundingClientRect()` 量到的是缩放后的视觉像素,除以它才是与 `project()` / `unproject()` 同一套坐标。指针事件(`onHover` / `onPointer` / `getPointer`)与 `project` / `unproject` 已经是布局像素,直接用;`onViewport` 回调也会带上这个字段。**运行期**改 CSS `zoom` 不用自己做什么:内容盒与设备像素两档 `ResizeObserver` 各挂一个实例(同一个实例对同一元素再 `observe` 一次是改选项、会把前一次顶掉),放大 / 缩小都会自己补一次重排(逐帧实测:第 2 帧起显示比例 / 备份像素 / 标签偏移 / 指针命中全部对齐,demo 的「宿主缩放」滑杆来回拉也跟得上),运行期改祖先的 `transform: scale` 不动布局、观察不到,把新比例交给 `view.resize()`(或在窗口 resize 时一起改)即可同步;显示比例 1% 以内按 1 处理、夹在 0.1 ~ 8,鹰眼图的备份像素在这条乘积小于 1 时按 1 倍开(轻微超采样,只会更清楚)。
|
|
17
|
-
- **尺寸的三个层次**(节点与线路都有):要素自身的 `size` / `width` → 规则的 `size` / `width` → 全局 `pointStyle` / `lineStyle`;再乘 `pointSizeScale` / `lineWidthScale`(常数倍数)与地图缩放的联动指数 `pointZoomScale` / `lineZoomScale`(0 表示不跟随,1
|
|
17
|
+
- **尺寸的三个层次**(节点与线路都有):要素自身的 `size` / `width` → 规则的 `size` / `width` → 全局 `pointStyle` / `lineStyle`;再乘 `pointSizeScale` / `lineWidthScale`(常数倍数)与地图缩放的联动指数 `pointZoomScale` / `lineZoomScale`(0 表示不跟随,1 表示与地图同倍率)。
|
|
18
18
|
|
|
19
19
|
- **经纬度与 GeoJSON**:配了 GeoJSON 背景(`background.geoJson`)就多一套换算:`lngLatToWorld` / `worldToLngLat` 把经纬度接到画出来的世界坐标上(`aspectScale` 只压经度、绕整体范围中心),`lngLatToScreen` / `screenToLngLat` 直接连到画布 CSS 像素;数据不在底图的坐标系里时用 `createGeoMapper` / `mapDataToGeoJson` 把点、线路与通道搬到画出来的底图上,见「经纬度与数据映射」。
|
|
20
20
|
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
| `lngLatToWorld(lng, lat)` / `worldToLngLat(x, y)` | 经纬度 ↔ 世界坐标 | 已经含 `aspectScale`:`lngLatToWorld(rawBounds.minX, …)` 正好落在底图左边缘,与画出来的底图完全对齐 |
|
|
29
29
|
| `lngLatToScreen(lng, lat)` / `screenToLngLat(x, y)` | 经纬度 ↔ 画布 CSS 像素 | 画布内的像素坐标(左上角为原点),与 `onPointer` / `getPointer()` 用的是同一套 |
|
|
30
30
|
|
|
31
|
-
`getPointer()` 与 `onPointer` 回调共用同一份光标状态 `{ inside, screen, world, lngLat }`:`screen` 是画布 CSS 像素、`world` 是世界坐标、`lngLat` 是反算出来的经纬度(没有 GeoJSON 背景时为 `null`);鼠标移出画布时 `inside: false`,其余字段保留最后一次的值。各类指针载荷(`onHover` / `onClick` / `onDblClick` / `onPointerDown` / `onPointerUp` / `onContextMenu
|
|
31
|
+
`getPointer()` 与 `onPointer` 回调共用同一份光标状态 `{ inside, screen, world, lngLat }`:`screen` 是画布 CSS 像素、`world` 是世界坐标、`lngLat` 是反算出来的经纬度(没有 GeoJSON 背景时为 `null`);鼠标移出画布时 `inside: false`,其余字段保留最后一次的值。各类指针载荷(`onHover` / `onClick` / `onDblClick` / `onPointerDown` / `onPointerUp` / `onContextMenu`)在配了 GeoJSON 背景时也会多带一个 `lngLat` 字段。
|
|
32
32
|
|
|
33
33
|
数据本身不在底图的坐标系里(例如底图是经纬度、数据是另一套投影坐标)时,用映射器把数据搬到画出来的底图上:
|
|
34
34
|
|
|
@@ -138,6 +138,7 @@ createGisView(container, { points, lines, channels })
|
|
|
138
138
|
| `visible` | `boolean` | `false` 时不画 |
|
|
139
139
|
| `decorations` | `GisViewLineDecoration[]` | 沿线挂的图片 / SVG,见「线路上的装饰」 |
|
|
140
140
|
| `direction` | `GisViewLineDirectionInput` | 这条线自己的方向箭头(静态,不跑动):`true` 用 `options.lineDirection`、对象逐字段覆盖、`false` / `null` 关掉;按弧长摆、朝向跟着切向(起点 → 终点),见「线路方向箭头(lineDirection)」 |
|
|
141
|
+
| `forward` | `boolean` | 业务正向,默认 `true`:从 `from` / `path[0]` 走向 `to` / `path[last]`。写 `false` 时装饰位置与朝向、方向箭头、线路动画都按反方向解释;它与 `effect.reverse` / `direction.reverse` 是异或关系(反两次等于正一次),不改写 `path` 本身 |
|
|
141
142
|
| `lineLabel` / `lineLabelPosition` / `lineLabelVisibility` / `lineLabelOffset` / `lineLabelParallel` | | 这条线自己的标签配置(`lineLabelParallel` 是这条线自己的「与线路平行」开关) |
|
|
142
143
|
| `labels` | `GisViewItemLabel \| GisViewItemLabel[]` | 这条线上的标签清单(逐条写,与节点的 `labels` 同一套,额外认 `parallel`),见「标签(labels,导入即回显)」 |
|
|
143
144
|
| `tooltip` | `GisViewTooltipContent \| false` | 这条线的提示内容 |
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
| `points` | `GisViewPoint[]` | `[]` | 点数据,`x` / `y` 为世界坐标(经纬度、投影米或任意平面坐标) |
|
|
20
20
|
| `lines` | `GisViewLine[]` | `[]` | 线数据,`start` / `end` 支持 `{ x, y }` 或 `[x, y]`,折线用 `path`,端点可用 `from` / `to` 绑定点 id |
|
|
21
21
|
| `channels` | `GisViewChannel[]` | `[]` | 通道:把若干条线路组织成并行敷设的多回线走廊,回线几何由骨架折线按偏移推导;两端可用 `from` / `to` 绑在节点上 |
|
|
22
|
+
| `pointCluster` | `boolean \| GisViewPointClusterOptions` | 关 | 点聚合:`true` 使用缺省档(屏幕半径 60px / 至少 2 点 / 不限缩放),对象写法可调 `enabled` / `radius` / `minPoints` / `maxZoom`。聚合圆替代密集原始点参与绘制、拾取、快照与导出;原始 `points` / `getData()` 不变,缩放超过 `maxZoom` 后恢复逐点显示,见「点聚合(pointCluster)」 |
|
|
22
23
|
| `channelWidth` | `number` | `0.02` | 通道宽度的世界单位写法(`tangent` 模式下是最外侧两条回线中心的间距,`inset` 模式下先按它算再收),**只在 `nodeWidth` 为 0 或两端没绑节点时才真正决定宽度**;单个通道可用 `width` 覆盖 |
|
|
23
24
|
| `channelInset` | `number` | `0` | `offsetMode: 'inset'` 时从切点收 / 放的比例(占通道宽度):正数内收(最多 0.42),**负数外收**(最多 -0.5,可用区间撑到 2 倍宽);单个通道可用 `inset` 覆盖,见「通道与多回线」 |
|
|
24
25
|
| `channelNodeWidth` | `number` | `1` | 节点宽度倍数:通道宽度按两端节点尺寸取的倍数,`1` 表示回线正好铺在节点两边、节点放大回线跟着变宽,`0` 表示所有通道退回 `width` / `channelWidth` 的世界单位写法,单个通道可用 `nodeWidth` 覆盖 |
|
|
@@ -37,7 +38,7 @@
|
|
|
37
38
|
| `prebake` | `GisViewPrebakeOptions \| true` | 关 | 贴图符号预热:把「这次画面会出现什么」提前告诉组件 —— 两种写法:`combos` 逐组合(精确,`getSymbolCombos()` 收出来的那份)/ `symbols × pointColors × sizes` 与 `lineColors × 线路动画图标` 全排列(省事,颜色与尺寸由同一个字段决定时会多烤很多)—— 第一帧之前就烤好,画到它们时命中的是现成的贴图(省掉解码 + 光栅化那一下);组合数与数据量无关,不配就是从前那条按需路径。读数 `getPrebake()` / `getSymbolCombos()`、手动再烤一遍 `runPrebake()`,见「贴图符号预热(prebake)」 |
|
|
38
39
|
| `label` | `GisViewLabelOptions \| GisViewLabelOptions[]` | 无 | 节点标签:内容 / 位置 / 显隐 / 避让 / 拖动与编辑都可配,**写数组就是同一个节点上多条标签**,与 `lineLabel` 共用一套避让网格,见「节点标签」 |
|
|
39
40
|
| `labelOptimize` | `boolean` | `false` | 标签显示优化开关:**缺省关 = 强制显示**(不避让、不按 `maxCount` 截断、不设 `scanLimit` / 扫描预算,节点 / 线路的每个可见要素该出现的标签一条不少);写 `true` 与从前一致 —— 避让 / 换落点 / 数量上限 / 候选上限全部生效。标签订得密、数据量大(十万级)时建议打开,见「标签显示优化开关」 |
|
|
40
|
-
| `labelRender` | `'auto' \| 'dom'` | `'auto'` | 纯文本标签的容器渲染方式:`auto` 在强制显示档(`labelOptimize` 未开且未进密集档)下,同一层纯文本标签达到 1024 条时改画到一张 Canvas
|
|
41
|
+
| `labelRender` | `'auto' \| 'canvas' \| 'dom'` | `'auto'` | 纯文本标签的容器渲染方式:`auto` 在强制显示档(`labelOptimize` 未开且未进密集档)下,同一层纯文本标签达到 1024 条时改画到一张 Canvas;`canvas` 不受数量阈值限制,优化档 / 密集档也强制画布并直接用画布尺寸参与避让;`dom` 始终逐条建 `.gis-view__label`。HTML / 元素内容 / 可拖拽 / 可编辑 / 超出 Canvas 样式能力的标签仍走 DOM。只影响容器,不改内容、锚点、显隐以及 `maxCount` / `when` / `scanLimit` 等优化策略,见「标签容器渲染(labelRender)」 |
|
|
41
42
|
| `lineLabel` | `GisViewLineLabelOptions \| GisViewLineLabelOptions[]` | 无 | 线路标签:位置沿线走(比例 / 百分比 / 绝对距离),内容、避让、显隐都可配,与节点标签共用一套避让网格;**写数组就是同一条线上多条标签**,见「线路标签」 |
|
|
42
43
|
| `labelStates` | `GisViewLabelState[]` | 无 | 标签的运行时状态(`getLabelStates()` 的那一份:拖出来的偏移、改过的内容与样式、运行时加的标签、隐藏覆盖):创建时喂回来就回显,等价于创建之后调 `setLabelStates(states)`;`updateOptions({ labelStates })` 同样认。`exportData({ format: 'input' })` 的结果里就叫 `labelStates`,存档 → 回灌直接接上 |
|
|
43
44
|
| `graphics` | `GisViewGraphic[]` | 无 | 与节点无关的扩展图形:按世界坐标放 SVG 路径 / 图片 / Canvas,支持锚点、偏移、旋转、透明度、`zIndex` 与 `scaleWithView`;位于画布之上、标签之下,运行时用 `addGraphic` / `addGraphics` / `updateGraphic` / `removeGraphic` / `clearGraphics` 增删改,见「扩展图形(graphic)」 |
|
|
@@ -48,11 +49,12 @@
|
|
|
48
49
|
| `searchWorker` | `boolean \| GisViewSearchWorkerOptions` | `{ threshold: 20000 }` | [异步搜索](14-视图与筛选.md#搜索与定位)是否用 Web Worker 计算:默认点 + 线总数超过阈值才用,`false` 表示 `searchAsync` 也同步算;同步的 `search` 一直在主线程算,不受这一项影响 |
|
|
49
50
|
| `pointHoverStyle` / `pointSelectStyle` | `GisViewPointStyle` | 无 | 点的悬停 / 选中样式;没配就不改变外观(悬停仍然触发回调与提示、选中仍然进选中集合),要反馈就自己配一份 |
|
|
50
51
|
| `lineHoverStyle` / `lineSelectStyle` | `GisViewLineStyle` | 无 | 线的悬停 / 选中样式;没配同样不改变外观 |
|
|
52
|
+
| `cascadeHighlight` | `boolean \| GisViewCascadeHighlightOptions` | 关 | 点击级联高亮:`true` 亮节点 + 直连线路;对象可设 `enabled`、`scope`、`triggerOnClick`、`triggerOnMultiSelect`、`triggerOnBoxSelect`、独立的 `pointStyle` / `lineStyle` 与 `clearOnEmptyClick`。它不改选中集,见「点击级联高亮」 |
|
|
51
53
|
| `pointMultiSelectStyle` / `pointBoxSelectStyle` | `GisViewPointStyle` | 无 | 多选(Ctrl + 点击)/ 框选(Shift + 拖动,可改 `shortcuts.boxSelect`)命中的点样式,缺省与 `pointSelectStyle` 一致,单个点可用 `multiSelectStyle` / `boxSelectStyle` 覆盖 |
|
|
52
54
|
| `lineMultiSelectStyle` | `GisViewLineStyle` | 无 | 多选命中时的线样式,缺省与 `lineSelectStyle` 一致,单条线可用 `multiSelectStyle` 覆盖;框选出来的线路仍走 `lineSelectStyle`(线路没有单独的框选样式) |
|
|
53
55
|
| `defaultHighlight` | `boolean` | `false` | 没有配置状态样式时是否仍用尺寸 / 宽度增幅与强调环画出内置强调;默认 `false`(不配样式就不改变外观),设为 `true` 可退回旧行为 |
|
|
54
|
-
| `pointSizeScale` / `lineWidthScale`、`pointZoomScale` / `lineZoomScale`、`zoomBaseScale` | `number` | `1` / `0` | 两组系数各管一件事,不重复:`pointSizeScale` / `lineWidthScale` 是与地图无关的整体放大(常数倍数,屏幕上的大小因此恒定),`pointZoomScale` / `lineZoomScale` 是「跟随地图缩放」的指数(0 表示不跟随,1 表示与地图同倍率放大,0.5 是地图放大 4 倍、要素放大 2 倍),绘制尺寸是两者相乘;`zoomBaseScale`
|
|
55
|
-
| `
|
|
56
|
+
| `pointSizeScale` / `lineWidthScale`、`pointZoomScale` / `lineZoomScale`、`zoomBaseScale` | `number` | `1` / `0` | 两组系数各管一件事,不重复:`pointSizeScale` / `lineWidthScale` 是与地图无关的整体放大(常数倍数,屏幕上的大小因此恒定),`pointZoomScale` / `lineZoomScale` 是「跟随地图缩放」的指数(0 表示不跟随,1 表示与地图同倍率放大,0.5 是地图放大 4 倍、要素放大 2 倍),绘制尺寸是两者相乘;`zoomBaseScale` 是联动基准,缺省取首次适应视图时的比例 |
|
|
57
|
+
| `fitSpacing` | `boolean \| GisViewFitSpacingOptions` | 关 | 适应视图的节点间距兜底:`true` 用 `{ minDistance: 24, maxZoom: 0 }`,对象可改最小中心距(CSS 像素)与相对普通适应比例的上限(`0` 表示不限);只在首次默认适应与 `fitView()` 生效,远处孤立点允许落到视口外,见「适应视图的节点间距(fitSpacing)」 |
|
|
56
58
|
| `boxSelect` | `boolean` | `false` | 是否允许按住框选快捷键(`shortcuts.boxSelect`,默认 Shift)拖动鼠标框选要素;**缺省关**,写 `boxSelect: true` 或 `features: { boxSelect: true }` 才开。框选默认只收节点,`selectionKinds` 可把线路 / 通道也纳入 |
|
|
57
59
|
| `multiSelect` | `boolean` | `false` | 多选开关:打开后不用按修饰键,直接单击节点 / 线路就取反累加选中(与按住 `shortcuts.multiSelect` 点击同一套行为、同一个 `multiSelectStyle`;取反那一下不经过 `onClick`,`onSelectChange.action.type` 是 `toggleSelect`);**缺省关**,关着时多选走框选(`boxSelect`)与按住多选快捷键(默认 Ctrl / ⌘)。运行时 `updateOptions({ multiSelect })` 切换只重画一帧、不重排场景 |
|
|
58
60
|
| `selectionKinds` | `GisViewSelectionKindsInput` | 无(框选只收节点;Ctrl 多选收节点 / 线路 / 通道) | 框选与 Ctrl / 多选点击的类型过滤:`'point'` 节点、`'line'` 通道外的独立线路、`'channel'` 通道回线;可写数组任意组合,`'all'` / `true` 全开,`false` / `null` 全关。通道回线只归 `channel` 管,通道外的线路只归 `line` 管;通道回线仍按 `channelSelectMode` 摊开。不写时保留旧口径;普通单选与 `select` / `selectFeatures` 不受它限制。运行时走 `updateOptions({ selectionKinds })`,见「框选」与「选择类型过滤」 |
|
|
@@ -68,10 +70,11 @@
|
|
|
68
70
|
| `gridSize` | `number` | `96` | 网格线的屏幕目标间距,实际步长吸附到 1 / 2 / 5 × 10^n |
|
|
69
71
|
| `showGrid` | `boolean` | `false` | 是否绘制网格:与其它功能开关同一条口径,**缺省关**,写 `showGrid: true` 才画 |
|
|
70
72
|
| `interactive` | `boolean` | (缺省全关) | 查看类交互的「详细配置手动打开」写法:写 `true` 打开拖拽平移 / 滚轮缩放 / 右键回调(等价 `pan` / `zoom` / `contextMenu` 三个开关),不写就是全关 |
|
|
71
|
-
| `preventContextMenu` | `boolean` | `true` | 组件接住右键时是否收掉浏览器的系统菜单(`contextmenu` 的默认行为):`contextMenu` 开着(或 `interactive: true` / `features: 'view'`)时组件才接右键,接住时一律 `preventDefault()`,点 / 线 / 空白 / 通道都一样;想让系统菜单自己弹就写 `false`(`onContextMenu`
|
|
73
|
+
| `preventContextMenu` | `boolean` | `true` | 组件接住右键时是否收掉浏览器的系统菜单(`contextmenu` 的默认行为):`contextMenu` 开着(或 `interactive: true` / `features: 'view'`)时组件才接右键,接住时一律 `preventDefault()`,点 / 线 / 空白 / 通道都一样;想让系统菜单自己弹就写 `false`(`onContextMenu` 照常发)。右键整个不接时(`contextMenu` 缺省关)系统菜单自然照弹 |
|
|
72
74
|
| `clickable` | `boolean` | (缺省全关) | 查看类交互的「详细配置手动打开」写法:写 `true` 打开悬停高亮与点击选中(等价 `hover` / `select` 两个开关),要素自身可用 `clickable: false` 逐个关掉 |
|
|
73
75
|
| `draggable` | `boolean` | `false` | 点是否可拖拽,单个点可用 `draggable` 覆盖;**缺省关**,写 `draggable: true` 或 `features: { drag: true }` 才开 |
|
|
74
76
|
| `liveDrag` | `boolean` | `true` | 拖动节点时线路是否实时跟随:`false` 时拖动期间线路与通道原地不动,松手(`pointerup`)后一次性更新到新位置 |
|
|
77
|
+
| `lineFollowsNode` | `boolean` | `true` | 线路 / 通道是否跟随节点的生命周期:`true` 时隐藏、删除、筛选收起节点会连同绑定线路与通道一起处理;`false` 时节点退场只影响节点,线路 / 通道停在最后一份坐标与解析尺寸。筛选没有显式写 `cascade` 时,关闭它会把默认联动从 `'binding'` 改为 `false`;显式 `cascade` 始终优先。运行时用 `updateOptions({ lineFollowsNode })` 切换,见「筛选」 |
|
|
75
78
|
| `shortcuts` | `GisViewShortcuts` | 见「快捷键」 | 所有快捷键都可自定义:框选 / 多选 / 加点 / 复制 / 粘贴 / 取消 / 删除 / 适应视图,没写的动作沿用默认值,写 `false` 等于关掉这个动作的快捷键 |
|
|
76
79
|
| `copy` | `GisViewCopyOptions` | 缺省关 | 复制节点(**写了这份配置才算开**,`enabled: false` 显式关掉):`enabled` 开关、`offset` 落点偏移(默认 `[28, 24]` 像素)、`autoCommit`(交互入口落地前是否自动确认:不写就是落地,`false` 停在预览态等 `commitPointCopy()` / 载荷里的 `payload.commit()`)、`idPrefix`(默认 `copy-`)、`createId` / `createItem` 定制复制品,见「节点复制」 |
|
|
77
80
|
| `remove` | `GisViewRemoveOptions` | 缺省关 | 删除选中的拐点 / 线路 / 节点(**写了这份配置才算开**,`enabled: false` 显式关掉):`enabled` 开关、`scope`(`confirm()` 不带参数时的缺省范围:`'lines'` 只删选中的回线 / `'groups'` 连所在分组 / `'channels'` 连整条通道,缺省 `'lines'`)、`confirm`(不写停在 `pending` 等使用方裁决 / `false` 直接删 / 函数自行裁决,支持 Promise)。Delete 键与 `requestRemove()` 都先出一份「要删什么、连带什么」的载荷,确认之后才动数据;删节点会连挂在它身上的线路与被它锚定的通道一起删,见「删除(remove)」 |
|
|
@@ -103,11 +106,11 @@
|
|
|
103
106
|
| 分组 | 字段 |
|
|
104
107
|
| --- | --- |
|
|
105
108
|
| 总开关与历史 | `features` · `history` |
|
|
106
|
-
| 数据与背景 | `points` · `lines` · `channels` · `background` |
|
|
109
|
+
| 数据与背景 | `points` · `lines` · `channels` · `pointCluster` · `background` |
|
|
107
110
|
| 通道几何 | `channelWidth` · `channelInset` · `channelNodeWidth` · `channelTangentInset` · `channelMaxGroups` · `channelGroupMaxLines` · `channelDraftStyle` · `channelSelectMode` · `channelWaypointDragMode` |
|
|
108
111
|
| 样式与规则 | `pointStyle` · `lineStyle` · `pointRules` / `lineRules` · `heatmap` · `effects` · `lineDirection` · `prebake` · `label` · `labelOptimize` · `labelRender` · `lineLabel` · `labelStates` · `tooltip` · `pointSizeScale` / `lineWidthScale`、`pointZoomScale` / `lineZoomScale`、`zoomBaseScale` · `cursorStyle` · `gridColor` · `gridSize` · `showGrid` |
|
|
109
112
|
| 状态样式与选中 | `pointHoverStyle` / `pointSelectStyle` · `lineHoverStyle` / `lineSelectStyle` · `pointMultiSelectStyle` / `pointBoxSelectStyle` · `lineMultiSelectStyle` · `defaultHighlight` · `selectionBoxStyle` · `selectionOnTop` · `waypointStyle` / `waypointSelectStyle` |
|
|
110
|
-
| 交互开关 | `boxSelect` · `multiSelect` · `waypointEditable` · `waypointVisibility` · `interactive` · `preventContextMenu` · `clickable` · `draggable` · `liveDrag` · `shortcuts` · `copy` · `remove` · `merge` |
|
|
113
|
+
| 交互开关 | `boxSelect` · `multiSelect` · `waypointEditable` · `waypointVisibility` · `interactive` · `preventContextMenu` · `clickable` · `draggable` · `liveDrag` · `lineFollowsNode` · `shortcuts` · `copy` · `remove` · `merge` |
|
|
111
114
|
| 视图与相机 | `minScale` / `maxScale` · `fitPadding` · `fitOnInit` · `initialView` · `zoomStep` |
|
|
112
115
|
| 画质与渲染 | `quality` · `width` / `height` · `pixelRatio` · `maxCanvasPixels` · `antialias` · `interactionThinLines` · `interactionNoMsaa` · `renderer` · `webglLayers` |
|
|
113
116
|
| 大数据(筛选 / 搜索 / 读数) | `denseMode` · `filter` · `filterWorker` · `searchWorker` · `progressiveInit` · `statsInterval` · `renderEmitInterval` |
|
|
@@ -192,6 +195,24 @@ const channels = [{
|
|
|
192
195
|
}]
|
|
193
196
|
```
|
|
194
197
|
|
|
198
|
+
#### `pointCluster`
|
|
199
|
+
|
|
200
|
+
- **类型**:`boolean | GisViewPointClusterOptions`
|
|
201
|
+
- **默认值**:关
|
|
202
|
+
- **说明**:点聚合。`true` 等价于 `{ enabled: true, radius: 60, minPoints: 2, maxZoom: 0 }`;对象写法里的 `enabled` 缺省 `true`,`radius` 是屏幕 CSS 像素半径(缺省 60,夹在 8 ~ 500),`minPoints` 是合成一个聚合圆所需的最少点数(缺省 2,最小 2),`maxZoom` 是相机比例相对 `zoomBaseScale` / 首次适应视图比例的倍数,超过后展开原始点(`0` 表示不限)。聚合用固定网格建组,单次按数据量 O(n) 扫描;平移复用当前成员,只在缩放、配置、数据、选中、拖动、合并或复制预览变化时重算。聚合期间发散初始化和追加式补点暂停;选中、拖动、待确认合并与复制预览中的点强制保持单成员。它只改展示与命中结果:`getData()` 仍是原始数据,`listPoints({ visibleOnly: false })` 仍能列全,默认 `visibleOnly: true` 会跳过被聚合圆收起的成员;`getClusters()` 含单成员展示组,`getPointCluster()` 返回归一化配置与当前 `active`,统计在 `getStats().clusterCount` / `clusterPointCount` / `clusterMs`。点击聚合圆只发 `clusterClick` / `onClusterClick`,不选中内部节点。推荐与 `denseMode` 配合使用;需要看真实符号时用 `maxZoom`,或直接把 `pointCluster` 设为 `false`。演示见 `?demo=cluster`
|
|
203
|
+
- **示例**:
|
|
204
|
+
|
|
205
|
+
```js
|
|
206
|
+
const view = createGisView(container, {
|
|
207
|
+
points,
|
|
208
|
+
pointCluster: { radius: 64, minPoints: 3, maxZoom: 2.5 }
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
view.updateOptions({ pointCluster: false }) // 关掉,原始点全部恢复
|
|
212
|
+
const groups = view.getClusters() // 含 count: 1 的单成员
|
|
213
|
+
const { active, radius } = view.getPointCluster() // 当前缩放档是否仍在聚合
|
|
214
|
+
```
|
|
215
|
+
|
|
195
216
|
#### `background`
|
|
196
217
|
|
|
197
218
|
- **类型**:`GisViewBackground`
|
|
@@ -388,9 +409,9 @@ view.updateOptions({ prebake: { combos: view.getSymbolCombos().combos } })
|
|
|
388
409
|
|
|
389
410
|
#### `labelRender`
|
|
390
411
|
|
|
391
|
-
- **类型**:`'auto' | 'dom'`
|
|
412
|
+
- **类型**:`'auto' | 'canvas' | 'dom'`
|
|
392
413
|
- **默认值**:`'auto'`
|
|
393
|
-
-
|
|
414
|
+
- **说明**:纯文本标签的容器画法。`auto` 只在**强制显示档**(缺省 `labelOptimize: false` 且 `denseMode` 未激活)启用:节点层或线路层里可画布的纯文本标签达到 **1024** 条时,该层改用一张 Canvas,不再逐条建 `.gis-view__label`。`canvas` 显式选择画布,不受 1024 条阈值限制,`labelOptimize: true` 或密集档也生效;`maxCount` / `when` / `scanLimit` / 避让与换落点仍照常执行,只是尺寸直接取画布测量结果,不创建也不测量 DOM。`dom` 始终逐条建 DOM,保持旧行为。`html: true`、函数返回 `HTMLElement`、可拖拽 / 可编辑,以及带 Canvas 不支持样式的标签在三种模式下都仍保留 DOM。它和 `html` 是两件事:`html` 只控制字符串按文本还是 HTML 解析,`html: false` 仍然会建 `div`;见「标签容器渲染(labelRender)」
|
|
394
415
|
- **参考**:见「标签容器渲染(labelRender)」一节
|
|
395
416
|
|
|
396
417
|
#### `lineLabel`
|
|
@@ -441,12 +462,12 @@ view.clearGraphics()
|
|
|
441
462
|
- **说明**:两组系数各管一件事,不重复:`pointSizeScale` / `lineWidthScale` 是与地图无关的整体放大(常数倍数,屏幕上的大小因此恒定),`pointZoomScale` / `lineZoomScale` 是「跟随地图缩放」的指数(0 表示不跟随,1 表示与地图同倍率放大,0.5 是地图放大 4 倍、要素放大 2 倍),绘制尺寸是两者相乘;`zoomBaseScale` 是联动基准,缺省取首次适应视图时的比例
|
|
442
463
|
- **参考**:见「点配置」一节,子字段在那里的表里逐个展开
|
|
443
464
|
|
|
444
|
-
#### `
|
|
465
|
+
#### `fitSpacing`
|
|
445
466
|
|
|
446
|
-
- **类型**:`boolean`
|
|
447
|
-
-
|
|
448
|
-
-
|
|
449
|
-
-
|
|
467
|
+
- **类型**:`boolean | GisViewFitSpacingOptions`
|
|
468
|
+
- **默认值**:关
|
|
469
|
+
- **说明**:适应视图的节点间距兜底。普通适应按数据包围盒铺满,远处多一个孤立点就会把比例压小、主体节点挤成一团;打开后先按普通规则算出适应比例,再用**可见节点最近的正中心距**反推一个更高的比例(最近距离达到 `minDistance` 为止)。**只改比例,不改中心**:相机中心仍取普通适应的包围盒中心,最近节点对并列时不挑中点、不跳视点。`maxZoom` 是相对普通适应比例的上限,`0` 表示不限;两种情况仍受 `maxScale` 约束。重合坐标不算有效间距,少于两个不同位置时不调整。显式写了 `initialView.scale` / `zoom` 时以显式值为准;运行时 `updateOptions` 不会当场移动相机,需要再调 `fitView()`
|
|
470
|
+
- **参考**:见「适应视图的节点间距(fitSpacing)」一节
|
|
450
471
|
|
|
451
472
|
#### `cursorStyle`
|
|
452
473
|
|
|
@@ -505,6 +526,40 @@ createGisView(container, {
|
|
|
505
526
|
})
|
|
506
527
|
```
|
|
507
528
|
|
|
529
|
+
#### `cascadeHighlight`
|
|
530
|
+
|
|
531
|
+
- **类型**:`boolean | GisViewCascadeHighlightOptions`
|
|
532
|
+
- **默认值**:关
|
|
533
|
+
- **说明**:点击级联高亮,和选中集是两份互不污染的状态。点节点时亮自身、直接相连的线路和另一端节点;点线路 / 通道回线时只亮两端节点。直接选中的节点 / 线路始终走选中样式,只有邻接项套 `pointStyle` / `lineStyle`。变化会通过 `onCascadeHighlight` / `cascadeHighlight` 事件给出,读数用 `getCascadeHighlight()`
|
|
534
|
+
- **参考**:见「点击级联高亮」一节
|
|
535
|
+
- **子字段**:
|
|
536
|
+
|
|
537
|
+
| 字段 | 类型 | 缺省 | 说明 |
|
|
538
|
+
| --- | --- | --- | --- |
|
|
539
|
+
| `enabled` | `boolean` | `true` | 开关;写对象且 `enabled: false` 等于关闭 |
|
|
540
|
+
| `scope` | `'points' \| 'both'` | `'both'` | `points` 只亮节点;`both` 同时亮直连线路(通道回线也按线路处理) |
|
|
541
|
+
| `triggerOnClick` | `boolean` | `true` | 普通单击是否触发 / 更新级联。设 `false` 时单击只走选中,并收掉旧级联 |
|
|
542
|
+
| `triggerOnMultiSelect` | `boolean` | `true` | Ctrl / ⌘ 累加点击、以及 `options.multiSelect` 的累加单击是否触发级联;设 `false` 时多选只改选中集 |
|
|
543
|
+
| `triggerOnBoxSelect` | `boolean` | `false` | 框选 / `selectInBox()` 是否触发级联。打开后框内所有命中项一起算邻接并集,直接命中的项仍走框选样式 |
|
|
544
|
+
| `pointStyle` | `GisViewPointStyle` | 琥珀色描边、`sizeScale: 1.2` | 级联节点样式,整份替换;字段同 `pointStyle` |
|
|
545
|
+
| `lineStyle` | `GisViewLineStyle` | 琥珀色、`width: 2.6`、`opacity: 0.95` | 级联线路样式,整份替换;字段同 `lineStyle` |
|
|
546
|
+
| `clearOnEmptyClick` | `boolean` | `true` | 点空白处是否收掉级联;`false` 时保留当前读数 |
|
|
547
|
+
|
|
548
|
+
`true` 等价于全部缺省值(`scope: 'both'`、`triggerOnClick: true`、`triggerOnMultiSelect: true`、`triggerOnBoxSelect: false`)。框选触发时 `origin` 取框内按数据顺序的第一个命中项,作为这一批级联的代表来源。
|
|
549
|
+
- **示例**:
|
|
550
|
+
|
|
551
|
+
```js
|
|
552
|
+
createGisView(container, {
|
|
553
|
+
points, lines, channels,
|
|
554
|
+
cascadeHighlight: {
|
|
555
|
+
scope: 'points',
|
|
556
|
+
triggerOnBoxSelect: true,
|
|
557
|
+
pointStyle: { color: '#fff7ed', strokeColor: '#f59e0b', strokeWidth: 2, sizeScale: 1.2 }
|
|
558
|
+
},
|
|
559
|
+
onCascadeHighlight: payload => console.log(payload?.pointIndexes)
|
|
560
|
+
})
|
|
561
|
+
```
|
|
562
|
+
|
|
508
563
|
#### `pointMultiSelectStyle` / `pointBoxSelectStyle`
|
|
509
564
|
|
|
510
565
|
- **类型**:`GisViewPointStyle`
|
|
@@ -623,7 +678,7 @@ view.selectInBox(rect, { selectionKinds: 'channel' }) // 仅这一次只框通
|
|
|
623
678
|
|
|
624
679
|
- **类型**:`boolean`
|
|
625
680
|
- **默认值**:`true`
|
|
626
|
-
- **说明**:组件接住右键时是否收掉浏览器的系统菜单(`contextmenu` 的默认行为):`contextMenu` 开着(或 `interactive: true` / `features: 'view'`)时组件才接右键,接住时一律 `preventDefault()`,点 / 线 / 空白 / 通道都一样;想让系统菜单自己弹就写 `false`(`onContextMenu`
|
|
681
|
+
- **说明**:组件接住右键时是否收掉浏览器的系统菜单(`contextmenu` 的默认行为):`contextMenu` 开着(或 `interactive: true` / `features: 'view'`)时组件才接右键,接住时一律 `preventDefault()`,点 / 线 / 空白 / 通道都一样;想让系统菜单自己弹就写 `false`(`onContextMenu` 照常发)。右键整个不接时(`contextMenu` 缺省关)系统菜单自然照弹
|
|
627
682
|
|
|
628
683
|
#### `clickable`
|
|
629
684
|
|
|
@@ -643,6 +698,22 @@ view.selectInBox(rect, { selectionKinds: 'channel' }) // 仅这一次只框通
|
|
|
643
698
|
- **默认值**:`true`
|
|
644
699
|
- **说明**:拖动节点时线路是否实时跟随:`false` 时拖动期间线路与通道原地不动,松手(`pointerup`)后一次性更新到新位置
|
|
645
700
|
|
|
701
|
+
#### `lineFollowsNode`
|
|
702
|
+
|
|
703
|
+
- **类型**:`boolean`
|
|
704
|
+
- **默认值**:`true`
|
|
705
|
+
- **说明**:线路 / 通道是否跟随节点的生命周期。默认 `true`:节点被 `visible: false`、`removePoints` 或筛选收起时,绑定的线路和以它为端点的通道一起退场,删节点也会连带删除这些线路 / 通道。写 `false` 后只动节点:节点隐藏或筛掉时,线路与通道停在最后一次解析出的坐标、骨架与宽度;删除节点也不删线路 / 通道;节点仍在时拖动它,线路照常实时更新。筛选没有显式写 `cascade` 时,关闭它会把默认联动从 `'binding'` 改为 `false`;条件里显式写了 `cascade` 仍以显式值为准。运行时用 `updateOptions({ lineFollowsNode })` 切换,会按新口径重算当前筛选
|
|
706
|
+
- **参考**:见「筛选」与「通道与多回线」;筛选条件自身的字段见「[筛选](../manual/14-视图与筛选.md#筛选)」
|
|
707
|
+
- **示例**:
|
|
708
|
+
|
|
709
|
+
```js
|
|
710
|
+
const view = createGisView(container, { lineFollowsNode: false })
|
|
711
|
+
|
|
712
|
+
view.removePoints('station-1') // 只删节点;绑定线路 / 通道继续按最后坐标画
|
|
713
|
+
view.setFilter({ vn_kv: { gte: 525 } }) // 未写 cascade:只隐藏不符合条件的节点
|
|
714
|
+
view.updateOptions({ lineFollowsNode: true })
|
|
715
|
+
```
|
|
716
|
+
|
|
646
717
|
#### `shortcuts`
|
|
647
718
|
|
|
648
719
|
- **类型**:`GisViewShortcuts`
|
|
@@ -963,4 +1034,6 @@ const view = createGisView(container, {
|
|
|
963
1034
|
|
|
964
1035
|
---
|
|
965
1036
|
|
|
1037
|
+
**相关章节**:[07 指针与要素编辑](07-指针与要素编辑.md) · [09 通道与多回线](09-通道与多回线.md) · [14 视图与筛选](14-视图与筛选.md) · [16 实例方法总表](16-实例方法总表.md)
|
|
1038
|
+
|
|
966
1039
|
[← 02 坐标与数据](02-坐标与数据.md) · [手册目录](../GisView.md) · [04 事件与回调 →](04-事件与回调.md)
|
|
@@ -9,10 +9,12 @@
|
|
|
9
9
|
| `onReady` | `{ canvas, gl }` | WebGL2 上下文与缓冲区就绪 |
|
|
10
10
|
| `onSelect` | `GisViewSelectPayload \| null` | 选中状态变化:点击为 `{ items, box: null, originalEvent }`,框选(默认按住 Shift)为 `{ items, box, originalEvent }`,点击空白处清空时为 `null`;Ctrl 点击节点的累加选中也走这里 |
|
|
11
11
|
| `onClick` | `GisViewClickPayload \| null` | 单击要素或空白处(空白处为 `null`):`type` / `item` / `index` / `screen` / `coordinate` / `button` / `selection` / `originalEvent` 之外还有 `action`(`type` 是 `select` / `clearSelection` / `click`,`double` 说明这一下是不是双击里的第二下,`press` / `duration` / `longPress` 说明这一次按下想做什么、按了多久、算不算长按),见「指针事件」 |
|
|
12
|
+
| `onClusterClick` | `GisViewClusterClickPayload` | 点中多成员聚合圆:带 `id` / `count` / `pointIndexes` / `pointIds` / `bounds` / `radius` / `coordinate` / `screen` / `selection` / `action`(`action.type` 恒为 `clusterClick`、`action.target` 为 `cluster`)。这一条**不会同时发 `onClick`**,也不会改动选中集;聚合圆内部的原始节点不参与普通点击 |
|
|
12
13
|
| `onDblClick` | `GisViewClickPayload \| null` | 双击要素或空白处(320ms / 6px 内连续两次单击):`action.type` 是 `dblClick`、`action.double` 为 `true` |
|
|
13
14
|
| `onPointerDown` | `GisViewPointerPayload` | 左键 / 中键 / 右键按下:命中的要素、`button` / `buttons` 与光标位置;`action.type` 是这一次按下的**意图**(`dragPoint` / `dragWaypoint` / `boxSelect` / `pan` / `copy` / `channelDraft` / `contextMenu`…),`action.target` 说明点的是什么、`action.data` 直接给到那份数据,见「指针事件」 |
|
|
14
15
|
| `onPointerUp` | `GisViewPointerPayload` | 左键 / 中键 / 右键抬起,与 `onPointerDown` 成对:`action.type` 是**刚做完的那件事**(拖过就是 `dragPoint` / `dragWaypoint` / `boxSelect` / `pan`,没拖就是 `click`),`action.moved` 说明这一次是拖还是点,另带 `action.press`(按下时的意图)/ `duration`(按了多久)/ `longPress`(长按) |
|
|
15
|
-
| `onContextMenu` | `GisViewPointerPayload` |
|
|
16
|
+
| `onContextMenu` | `GisViewPointerPayload` | 每一次右键:点、线、通道、空白都只发这一条(要素信息在载荷里);`action.type` 固定是 `contextMenu`、`action.target` 说明点的是点 / 线 / 通道 / 空白。命中通道回线时,同一载荷另带 `channelContext`(几组 / 当前哪组 / 可用交互),不再有单独的通道右键回调。要自己弹菜单就在回调里渲染。**右键回调缺省关**(`contextMenu` / `interactive` 都没写时组件不接右键),写 `interactive: true` / `contextMenu: true` 或 `features: 'view'` 才发;接住右键时系统菜单默认已被收掉(`preventContextMenu` 缺省 `true`),想看系统菜单写 `preventContextMenu: false` |
|
|
17
|
+
| `onCascadeHighlight` | `GisViewCascadeHighlightInfo \| null` | 点击级联高亮变了:载荷带来源 `origin`(节点 / 线路 / 通道回线)、范围 `scope` 与亮着的 `points` / `lines` / `pointIndexes` / `lineIndexes`,与 `getCascadeHighlight()` 同一份;点空白或关掉开关时是 `null`。这条高亮不改选中集,事件总线名为 `cascadeHighlight` |
|
|
16
18
|
| `onHover` | `GisViewHoverPayload \| null` | 悬停要素变化(空白处 / 移出画布是 `null`):与拾取结果同一份读数(`type` / `index` / `item` + 通道字段,另有光标位置 `x` / `y` / `world` / `clientX` / `clientY`、选中集 `selection` 与 `lngLat`)+ `action`(`type` 恒为 `hover`、`target` 说明停在什么上面、`button` 是 `none`、`modifiers` 是当下的修饰键);程序化悬停 `hoverAt()` 也走同一条 |
|
|
17
19
|
| `onFilter` | `GisViewFilterResult` | 筛选完成(含 Worker 异步返回):隐藏的点 / 线下标、剩余可见数量、是否用了 Worker 与计算耗时 |
|
|
18
20
|
| `onCursor` | `[number, number] \| null` | 光标世界坐标,移出画布时为 `null` |
|
|
@@ -22,7 +24,6 @@
|
|
|
22
24
|
| `onPointMerge` | `GisViewPointMergePayload \| GisViewMergeResult \| GisViewMergeFailure \| GisViewMergeSelectedPayload` | 合并节点:拖到另一个节点上时先发 `pending`(组件不弹任何界面,在回调里调 `payload.confirm()` / `cancel()` 裁决,或存下来自己接界面),之后发 `confirm`(载荷里的 `item` 是合并结果,可改 / 可取消)、`cancel`,数据并完 / 并失败再发一条 `merge`(`ok: true` / `ok: false`);拖拽入口的载荷带 `trigger`(`'collision'` / `'center'`),说明这一次按哪种时机命中;框选 / 多选之后调 `mergeSelectedPoints()` 时**逐对发 `merge`**,收尾再发一条 `phase: 'mergeSelected'` 的汇总(`merged` 逐对列出、`skipped` 说明谁没并进去),见「节点合并」 |
|
|
23
25
|
| `onRemove` | `GisViewRemovePayload` | 删除请求(Delete 键 / `requestRemove()`):`pending` 时给一份载荷说明要删什么、连带什么、能按哪些范围删(`points` / `lines` / `waypoints` / `groups` / `channels` / `actions` / `counts`),确认之后发 `phase: 'remove'`(`result` 是结果)、取消发 `phase: 'cancel'`;组件不弹任何界面,弹不弹、怎么弹都由使用方决定(在回调里调 `payload.confirm(scope)` / `payload.cancel()`,或存下来自己接界面),见「删除(remove)」 |
|
|
24
26
|
| `onWaypointChange` | `GisViewWaypointPayload` | 拐点新增 / 选中 / 删除与拖动,`phase` 为 `add` / `select` / `remove` 或拖动时的 `start` / `move` / `end`,载荷带最新线路数据与所属集合的 `group_id`;通道内的回线共用骨架,载荷是**被操作的那条回线**的推导结果。同步后端只接改变数据的 `add` / `remove` / `end`,并用 `getChannelGroupWaypoints().path` 提交整份骨架,见「通道与多回线」 |
|
|
25
|
-
| `onChannelContextMenu` | `GisViewChannelContextPayload \| null` | 右键点中通道回线:给出这条通道的上下文(有几组、当前是哪一组、分组列表与可用交互),点空白处给 `null`(用它收框);**落在节点上时也给 `null`**(点的层级高于线,见「通道右键交互框」) |
|
|
26
27
|
| `onChannelDraft` | `GisViewChannelDraftPayload` | 新增通道草稿:`start` / `from` / `ready` / `pick` / `restart` / `cancel` / `commit` / `blocked`,两个节点的信息、`routing` / `path` 与可选方案都在载荷里(`path` 是中间拐点),见「新增通道」 |
|
|
27
28
|
| `onChannelDraftClick` | `GisViewChannelDraftPayload` | 草稿里**每点一次**都发一条:`step` 为 `1` 时拿到起点、`2` 时拿到终点(线路到此结束);加上 `phase: 'pick'` 时是点在空白或点回起点;载荷与 `onChannelDraft` 相同 |
|
|
28
29
|
| `onDecorationDraft` | `GisViewDecorationDraftPayload` | 动态装饰器草稿:`start` 开启 → `hover` 跟随命中线路或节点 / `leave` 移出收掉 → 左键在目标上松开发 `ready`(空白处不发)→ `commit` / `cancel`;`target` 为 `line` / `point` / `both`,`scope` 为 `line` / `group` / `channel`,节点侧 `placement` 为 `offset` / `fixed` / `pointer`,白名单、上限与重复策略见「动态装饰器草稿」 |
|
|
@@ -154,12 +155,12 @@ view.off('*') // 不传 handler = 摘掉这个事件的全部订阅,返回摘
|
|
|
154
155
|
| 约定 | 说明 |
|
|
155
156
|
| --- | --- |
|
|
156
157
|
| 事件名与回调一一对应 | `dataChange` 就是 `onDataChange`、`selectChange` 就是 `onSelectChange`,载荷完全同一份;`GisViewEventMap` 是事件名到载荷的类型表,`EVENT_NAMES` 是运行时的名字数组 |
|
|
157
|
-
| 要 DOM
|
|
158
|
+
| 要 DOM 事件的三个 | `pointerDown` / `pointerUp` / `contextMenu` 的载荷是 `{ payload, event }`(与回调的两个参数一一对应),其余事件的载荷与回调相同 |
|
|
158
159
|
| 回调抛错不扩散 | 订阅者抛错只走 `onError`:不打断其它订阅者,也不影响组件自己的流程 |
|
|
159
160
|
| 高频事件不白算 | 组件内部按「有没有人订阅」短路(`count(name) \|\| count('*')`):没人听的时候不构造载荷,`pointer` / `hover` / `render` 这些每帧级别的事件也可以直接订阅 |
|
|
160
161
|
| 订阅时机 | 创建时的 `ready` 与首次 `dataChange` 发生在 `createGisView` 返回之前,这两条要在 options 里写回调(`onReady` 等) |
|
|
161
162
|
|
|
162
|
-
全部事件名(与 `EVENT_NAMES` 一致):`ready`、`error`、`warning`、`viewport`、`cameraChange`、`cursor`、`hover`、`pointer`、`pointerDown`、`pointerUp`、`contextMenu`、`click`、`dblClick`、`labelClick`、`labelDrag`、`labelChange`、`labelContextMenu`、`labelDblClick`、`select`、`selectChange`、`pointDrag`、`pointCopy`、`pointMerge`、`remove`、`waypointChange`、`
|
|
163
|
+
全部事件名(与 `EVENT_NAMES` 一致):`ready`、`error`、`warning`、`viewport`、`cameraChange`、`cursor`、`hover`、`pointer`、`pointerDown`、`pointerUp`、`contextMenu`、`click`、`clusterClick`、`dblClick`、`labelClick`、`labelDrag`、`labelChange`、`labelContextMenu`、`labelDblClick`、`select`、`selectChange`、`cascadeHighlight`、`pointDrag`、`pointCopy`、`pointMerge`、`remove`、`waypointChange`、`channelDraft`、`channelDraftClick`、`decorationDraft`、`channelGroupChange`、`dataChange`、`dataRendered`、`filter`、`history`、`featureChange`、`qualityChange`、`optionChange`、`shortcut`、`stats`、`render`、`destroy`,加上 `'*'`。
|
|
163
164
|
|
|
164
165
|
## 功能开关
|
|
165
166
|
|
|
@@ -182,7 +183,7 @@ createGisView('#map', {
|
|
|
182
183
|
| 预设 | 效果 |
|
|
183
184
|
| --- | --- |
|
|
184
185
|
| `'edit'` | 全开(编辑类也一起打开),等价于 `features: true` |
|
|
185
|
-
| `'view'` | 只读浏览:一次打开查看类(平移缩放、悬停、选中、右键回调、键盘),`boxSelect` / `drag` / `waypoint` / `copy` / `merge` / `remove` / `channelDraft`
|
|
186
|
+
| `'view'` | 只读浏览:一次打开查看类(平移缩放、悬停、选中、右键回调、键盘),`boxSelect` / `drag` / `waypoint` / `copy` / `merge` / `remove` / `channelDraft` 仍关着 —— 「能看能选、改不动数据」 |
|
|
186
187
|
| `'static'` | 静态图:显式全关(含标签 / 提示 / 鹰眼图),只剩画布与数据;留着这个名字方便「从全开切回静态」 |
|
|
187
188
|
|
|
188
189
|
| 开关 | 关掉之后 | 没写时跟随 |
|
|
@@ -198,8 +199,7 @@ createGisView('#map', {
|
|
|
198
199
|
| `merge` | 拖到另一个节点上合并 | 写了 `merge` 且 `merge.enabled !== false`(缺省关) |
|
|
199
200
|
| `remove` | Delete 删除选中的拐点 / 线路 / 节点(先出删除载荷,确认之后才动数据) | 写了 `remove` 且 `remove.enabled !== false`(缺省关) |
|
|
200
201
|
| `channelDraft` | 新增通道草稿(程序化 `addChannel()` 不受限) | 关(缺省) |
|
|
201
|
-
| `
|
|
202
|
-
| `contextMenu` | 右键回调(关掉之后组件不接右键,浏览器菜单照常弹;通道右键框也要它先开着) | `interactive === true`(缺省关) |
|
|
202
|
+
| `contextMenu` | 右键回调(关掉之后组件不接右键,浏览器菜单照常弹;通道回线的 `channelContext` 也随这条一起给) | `interactive === true`(缺省关) |
|
|
203
203
|
| `tooltip` | 悬停提示(悬停样式与 `onHover` 还在) | 配了 `tooltip` 且没写 `enabled: false` |
|
|
204
204
|
| `label` / `lineLabel` | 节点 / 线路标签图层 | 配了且没写 `enabled: false`(不配不产生 DOM) |
|
|
205
205
|
| `minimap` | 内置鹰眼图 | 配了 `minimap` 且没写 `enabled: false` |
|
|
@@ -209,7 +209,7 @@ createGisView('#map', {
|
|
|
209
209
|
|
|
210
210
|
### 两层开关:`features` 与详细配置(重合的那几对)
|
|
211
211
|
|
|
212
|
-
同一件事常能写在两个地方(开关表 / 各自的详细配置),这不是重复,是「**一行说清整体口径**」与「**逐项微调**」两层。逐项对完
|
|
212
|
+
同一件事常能写在两个地方(开关表 / 各自的详细配置),这不是重复,是「**一行说清整体口径**」与「**逐项微调**」两层。逐项对完 17 个开关的关系是三类:
|
|
213
213
|
|
|
214
214
|
| 能力 | 开关 | 详细配置 | 谁说了算 |
|
|
215
215
|
| --- | --- | --- | --- |
|
|
@@ -30,6 +30,39 @@ createGisView(container, {
|
|
|
30
30
|
|
|
31
31
|
`clickable: false` 的要素既不会悬停高亮也不会被点中;`options.clickable: false` 则整体关闭拾取。
|
|
32
32
|
|
|
33
|
+
## 点击级联高亮(cascadeHighlight)
|
|
34
|
+
|
|
35
|
+
级联高亮是**另一份状态**,不走选中集:点击节点时算出它自己和直接相连的线路 / 另一端节点;点击线路或通道回线时只算这条线的两端节点。它默认关,`cascadeHighlight: true` 等价于 `{ scope: 'both', triggerOnClick: true, triggerOnMultiSelect: true, triggerOnBoxSelect: false }`;`scope: 'points'` 只亮节点,`both` 连直连线路一起亮。
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
const view = createGisView(container, {
|
|
39
|
+
points, lines, channels,
|
|
40
|
+
clickable: true,
|
|
41
|
+
cascadeHighlight: {
|
|
42
|
+
scope: 'both',
|
|
43
|
+
triggerOnClick: true,
|
|
44
|
+
triggerOnMultiSelect: true,
|
|
45
|
+
triggerOnBoxSelect: false,
|
|
46
|
+
pointStyle: { color: '#fff7ed', strokeColor: '#f59e0b', strokeWidth: 2, sizeScale: 1.2 },
|
|
47
|
+
lineStyle: { color: '#f59e0b', width: 2.6, opacity: 0.95 },
|
|
48
|
+
clearOnEmptyClick: true
|
|
49
|
+
},
|
|
50
|
+
onCascadeHighlight: payload => console.log(payload?.origin, payload?.pointIndexes, payload?.lineIndexes)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
view.getCascadeHighlight() // { origin, scope, points, lines, pointIndexes, lineIndexes } 或 null
|
|
54
|
+
view.updateOptions({ cascadeHighlight: { scope: 'points' } })
|
|
55
|
+
view.updateOptions({ cascadeHighlight: false }) // 关掉并收掉当前高亮
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- `pointStyle` / `lineStyle` 是级联专用的两套状态样式,缺省为琥珀色描边 / 线条,不需要先配 `pointSelectStyle` / `lineSelectStyle`。它们只作用于**被级联的邻接项**:直接选中的节点 / 线路仍走 `pointSelectStyle` / `lineSelectStyle`(多选 / 框选各走自己的那一档);没配选中样式时保持普通外观,也不会回落到级联样式;只有 `defaultHighlight: true` 时才补上内置选中强调。
|
|
59
|
+
- 触发方式三个开关彼此独立:`triggerOnClick` 管普通单击(缺省 `true`),`triggerOnMultiSelect` 管 Ctrl / ⌘ 累加点击与 `multiSelect`(缺省 `true`),`triggerOnBoxSelect` 管框选 / `selectInBox()`(缺省 `false`)。某一路关掉时,该操作只改变选中集,并把旧级联收掉;另一路仍可正常触发。
|
|
60
|
+
- 框选触发时,框内每个命中项都参与邻接计算,取并集后一次派发;`origin` 取框内按数据顺序的第一个命中项作代表。框内直接命中的项走 `boxSelectStyle` / `lineSelectStyle`,框外的邻接节点 / 线路才套级联样式。
|
|
61
|
+
- 点空白处是否收掉由 `clearOnEmptyClick` 控制,缺省 `true`。收掉、首次点亮、换节点 / 线路 / 通道或改范围都会发 `onCascadeHighlight` 与总线事件 `cascadeHighlight`;读数与回调收到的是同一份对象,收掉时是 `null`。
|
|
62
|
+
- `origin.target` 为 `point` / `line` / `channel`:通道回线在底层仍是线路,但 `origin` 会另带 `channelId` / `channelIndex` / `groupId` / `groupIndex` / `channel`,方便直接回显“点的是哪条通道的哪一组”。
|
|
63
|
+
- 数据整份更新后会按新的邻接关系刷新;来源被删除、被隐藏到不可拾取,或 `cascadeHighlight` 关掉时,高亮自动收掉。它不写 `selectionKeys`,`getSelectionData()` / `getSelections()` 不会因为级联高亮多出条目。
|
|
64
|
+
- 综合 Demo(`?demo=full`)的「视图 · 交互 → 交互开关与快捷键」面板已接入这项能力:可现场开关、在「节点 + 直连线路 / 只亮节点」之间切换,并直接读 `getCascadeHighlight()` 的来源、范围与节点 / 线路条数。
|
|
65
|
+
|
|
33
66
|
## 指针事件
|
|
34
67
|
|
|
35
68
|
鼠标的每一种动作都有回调,载荷里都能拿到「当前是哪个元素」:`onHover`(悬停)、`onClick`(单击左键)、`onDblClick`(双击)、`onPointerDown` / `onPointerUp`(按下与抬起,含左 / 中 / 右键)、`onContextMenu`(右键)。悬停是 `GisViewHoverPayload`、点击与双击是 `GisViewClickPayload` —— 都是在 `GisViewPickResult`(点 / 线 / 通道回线的 `type`、`index`、`item`、`screen`、`coordinate` 与通道字段)上再补光标位置与一份 `action`;按下 / 抬起 / 右键统一发 `GisViewPointerPayload`(同样是拾取结果 + `action`)。
|
|
@@ -95,13 +128,13 @@ createGisView(container, {
|
|
|
95
128
|
})
|
|
96
129
|
```
|
|
97
130
|
|
|
98
|
-
- 载荷形状一致,取信息只需认三处:`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` 一并给出;右键载荷还会在 `channelContext` 上带整份分组上下文。
|
|
99
132
|
- 配了 GeoJSON 背景时,以上载荷都多一个 `lngLat`:按光标的世界坐标(要素命中用 `coordinate`,悬停用最近一次光标位置)反算出来的真实经纬度,点 / 线 / 通道都一样;想自己换算就用 `worldToLngLat` / `screenToLngLat`,光标级别的屏幕坐标 + 世界坐标 + 经纬度看 `onPointer` 与 `getPointer()`。
|
|
100
133
|
- `onPointerDown` / `onPointerUp` 不改变组件行为:选中、拖拽、框选、拐点编辑照旧。左键的一次「点」(没有拖动)仍然走 `onClick` / `onDblClick`,两者是并列的,不会互相吞掉 —— 载荷里的 `action.type` 各说各话:按下是**意图**、松开是**刚做完的那件事**(`action.moved` 说明是拖还是点)、点击是**真正发生的那一件**。
|
|
101
134
|
- 点空白处照发:`onPointerDown` / `onPointerUp` 的 `action.target` 是 `empty`(开了平移时按下是 `pan` 的意图),`onClick` / `onDblClick` 的载荷是 `null`(选中在那一刻已经清空)——「点了空白」这件事也可以看 `onSelectChange` 的 `action.type: 'clearSelection'`。
|
|
102
135
|
- **中键按住就是临时平移**(`pan` 开关开着时):`onPointerDown` 的 `action.type` 是 `pan`、`action.button` 是 `'middle'`,按住拖动平移画布、松开结束(`onPointerUp` 的 `action.type` 也是 `pan`);这一路**不经过** `onClick`,中键也不会改选中 —— 想自己接中键(中键菜单 / 快捷操作)就按 `action.button === 'middle'` 认它。长按(触摸 / 触控笔)与中键一样有明确的读数:看松开 / 点击载荷的 `action.longPress` 与 `action.press` / `action.duration`。
|
|
103
|
-
- `onContextMenu`
|
|
104
|
-
- 命中的层级是**点 → 线 →
|
|
136
|
+
- `onContextMenu` 每次都只发这一条;命中通道回线时,分组上下文挂在同一份载荷的 `channelContext` 上(见「通道右键交互框」),不再额外发第二个回调。**右键缺省整个不接**(`contextMenu` 开关没开时系统菜单照弹、回调也不发);接住之后一律 `preventDefault()` 收掉系统菜单(点 / 线 / 空白 / 通道都一样),回调照常发。想自己弹菜单就写 `interactive: true` / `contextMenu: true` / `features: 'view'`,想让系统菜单自己弹出来就写 `preventContextMenu: false`。
|
|
137
|
+
- 命中的层级是**点 → 线 → 通道**:右键落在节点上时载荷是 `type: 'point'`,没有 `channelContext` —— 节点压在通道回线上(端点最常见)不会被当成通道右键;点空白处同样没有 `channelContext`,可以直接用它收框。
|
|
105
138
|
- 悬停是高频率回调:大数据量下建议只做节流的读数或轻量样式切换(demo 里的读数就是这么做的)。
|
|
106
139
|
|
|
107
140
|
- 命中的要素**在不在选中集里**、以及整份选中集有多少,载荷里直接给:`selected`(这一刻在不在选中集里)、`wasSelected`(`onClick` 给的是「点之前」的那一份,双击同理;右键与按下 / 松开都是「当下」,此时与 `selected` 相同)、`selection`(整份选中集的读数 `{ ids, count, points, lines, channels }`,通道回线按通道算一个)。左键 / 右键要自己接一套操作(按命中分支、弹自己的面板、决定要不要保留多选)时,看这三项就不用再去比对 `getSelectionData().ids`:
|
|
@@ -558,6 +591,8 @@ onPointMerge: async payload => {
|
|
|
558
591
|
|
|
559
592
|
接口调用不做确认,直接按规则合并:`view.mergePoints('a', 'b')`(来源、目标收 id、下标或 `{ id }` / `{ index }`)。合并的数据规则是:
|
|
560
593
|
|
|
594
|
+
这里的「合并样式」不是另一项样式配置,也不是新的 API;它指的是**合并后保留节点最终写进数据的 `size` 与 `symbol`**。Demo 的读数用它回答“合完会长什么样、用哪个图标”:尺寸取双方较大值、图标优先目标节点。它决定合并结果的外观,需要自定义时改 `merge.createItem(...)` 的返回值或 `payload.item` 即可。
|
|
595
|
+
|
|
561
596
|
- 节点数据缺省按「被并入的一端在前、保留端在后」合并(保留端优先,另一端独有的字段带过来),坐标与 id 取保留端;拖动合并确认里缺省保留碰撞目标,`keep: 'source'` 时保留拖动的来源节点;
|
|
562
597
|
- **图标大小取双方的最大值**:高电压往低电压合,原来的图标跟着变大(结果写成节点自己的 `size`,`sizeScale` 归 1);**图标类型优先目标节点**,目标没配符号才用来源的;
|
|
563
598
|
- 想自己决定就用 `merge.createItem(source, target, context)`,`context` 里带双方的 `sourceStyle` / `targetStyle`(`{ index, size, symbol, zIndex }`,样式链定下来的那一份,不含状态样式与热力倍率);
|
|
@@ -689,4 +724,6 @@ const view = createGisView('#map', {
|
|
|
689
724
|
|
|
690
725
|
---
|
|
691
726
|
|
|
727
|
+
**相关章节**:[03 配置项(options)](03-配置项.md) · [08 选中与拐点](08-选中与拐点.md) · [14 视图与筛选](14-视图与筛选.md) · [17 参数速查](17-参数速查.md)
|
|
728
|
+
|
|
692
729
|
[← 06 数据与场景更新](06-数据与场景更新.md) · [手册目录](../GisView.md) · [08 选中与拐点 →](08-选中与拐点.md)
|
|
@@ -74,6 +74,8 @@ view.selectFeatures(['station-1', { type: 'point', index: 5 }])
|
|
|
74
74
|
// ② 通道:整条通道的回线 / 通道里的某一组 / 通道里的某几条回线
|
|
75
75
|
view.selectFeatures({ type: 'channel', channelId: 'channel-a' })
|
|
76
76
|
view.selectFeatures({ channelId: 'channel-a', groupId: 'g-2' })
|
|
77
|
+
view.selectFeatures({ type: 'group', channelId: 'channel-a', groupId: 'g-2' })
|
|
78
|
+
view.selectFeatures({ type: 'group', groupId: 'g-2' }) // groupId 全局唯一时可省略通道
|
|
77
79
|
view.selectFeatures({ channelId: 'channel-a', lineIds: ['channel-channel-a-0', 'channel-channel-a-1'] })
|
|
78
80
|
view.selectFeatures({ channelIndex: 0, lineIndexes: [3, 4] })
|
|
79
81
|
|
|
@@ -90,6 +92,15 @@ view.selectFeatures({ type: 'channel', channelId: 'channel-a' }, { mode: 'remove
|
|
|
90
92
|
|
|
91
93
|
拾取载荷(`pickAt` 或指针事件里的那一份)与搜索命中里可能带着 `channelId` / `channelIndex` / `groupId` —— 那是「这条回线属于哪条通道」的上下文,不是「要选整条通道」:它们的 `type` / `kind` 写着 `line` / `point`,落地选中的就是那一条要素自己(与在画布上点它一个结果)。要整条通道,显式写 `{ type: 'channel', channelId: 'channel-a' }`。
|
|
92
94
|
|
|
95
|
+
聚焦同一套目标写法交给 `focusOn`,显式 `type` 还能解决节点与线路同 id 的歧义;整条通道可以写 `{ channelId }`,分组写 `{ type: 'group', channelId?, groupId }`(`groupId` 全局唯一时可省略 `channelId`)。节点、线路、通道与分组的取范围与缩放都走 `zoomToBounds`,不会因为类型不同换一套放大倍率:
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
view.focusOn({ type: 'point', id: 'shared-id' })
|
|
99
|
+
view.focusOn({ type: 'line', id: 'shared-id' })
|
|
100
|
+
view.focusOn({ type: 'channel', channelId: 'channel-a' })
|
|
101
|
+
view.focusOn({ type: 'group', channelId: 'channel-a', groupId: 'g-2' })
|
|
102
|
+
```
|
|
103
|
+
|
|
93
104
|
读回选中用 `getSelectionData()`,一次拿全(单击、多选、框选、接口选中都是这一份;只要下标与要素引用时用 `getSelections()`):
|
|
94
105
|
|
|
95
106
|
```js
|
|
@@ -133,6 +144,19 @@ view.selectFeatures('station-7', { mode: 'remove' }) // 与 deselect('sta
|
|
|
133
144
|
|
|
134
145
|
写 `waypointEditable: true`(缺省关)后,线路的中间顶点会画出可交互的拐点:按住 Ctrl 点击线路在点击位置插入拐点,单击选中,拖动即移动顶点、线路随之变成折线,双击或选中后按 Delete 删除。节点很密时 Ctrl 点击会先比较点到节点与点到线路的屏幕距离:**线路更近就按加点处理**,比节点远才走 Ctrl 多选节点,所以贴着节点云也能给线路补拐点。通道回线加点后的高亮范围与普通点选共用 `channelSelectMode`:`'line'` 只高亮点中的一条、`'group'` 连这一组、`'channel'` 整条通道。
|
|
135
146
|
|
|
147
|
+
### 代码选中拐点(selectWaypoint)
|
|
148
|
+
|
|
149
|
+
`selectWaypoint()` 走与点选同一份拐点状态:字符串 / 数字写法是「线路 id 或下标 + `pathIndex`」,对象写法是 `{ lineIndex, pathIndex }` 或 `{ lineId, pathIndex }`。`pathIndex` 用 `getWaypoints()` 返回的下标(首尾端点不算拐点)。选中成功时会把拐点所在线路一起选上,因此缺省 `waypointVisibility: 'selected'` 下拐点立即显示;`options.mode` 与 `selectFeatures` 一样决定线路怎么并进当前选中集(缺省换一份)。
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
view.selectWaypoint('line-a-b', 2)
|
|
153
|
+
view.selectWaypoint({ lineIndex: 0, pathIndex: 1 }, { mode: 'add' })
|
|
154
|
+
view.selectWaypoint({ lineId: 'line-a-b', pathIndex: 2 })
|
|
155
|
+
view.selectWaypoint(null) // 只取消拐点选中,不动要素选中集
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
找不到线路或下标不是可编辑拐点时不会凭空选中一个拐点;传 `null` 只清拐点高亮,原来的要素选中集保持不动。
|
|
159
|
+
|
|
136
160
|
需要完全停掉拐点编辑时写 `features: { waypoint: false }` 或 `waypointEditable: false`:Ctrl + 点击、`addWaypoint` / `addWaypoints` / `addChannelGroupWaypoint`、通道右键框「加拐点」、拖动已有拐点以及双击 / Delete 删除都会一起变成无操作,数据与历史都不动。拐点只有这一道总闸,没有 `waypointAdd` 之类的细分开关;`shortcuts.addWaypoint` 只决定加点用哪个组合键,不改变总闸。运行时也可以 `view.setFeatures({ waypoint: false })`,`getFeatures().waypoint` 读当前有效值。
|
|
137
161
|
|
|
138
162
|
拐点默认只在需要的时候出现:`waypointVisibility: 'selected'`(默认)下,只有被选中的线路(以及刚用 `addWaypoint` 加过拐点的线路)才画出拐点,点击空白处清空选中后拐点一起隐藏;改成 `'always'` 可以回到常显。`getWaypoints()` 返回当前显示中的拐点,`getWaypoints(lineIndex)` 只取某条线路的,拿到的是 `{ lineIndex, pathIndex, coordinate, selected }`。
|
|
@@ -210,4 +234,6 @@ view.getParallelGroups()
|
|
|
210
234
|
|
|
211
235
|
---
|
|
212
236
|
|
|
237
|
+
**相关章节**:[07 指针与要素编辑](07-指针与要素编辑.md) · [09 通道与多回线](09-通道与多回线.md) · [16 实例方法总表](16-实例方法总表.md) · [17 参数速查](17-参数速查.md) · [18 逐方法示例](18-逐方法示例.md)
|
|
238
|
+
|
|
213
239
|
[← 07 指针与要素编辑](07-指针与要素编辑.md) · [手册目录](../GisView.md) · [09 通道与多回线 →](09-通道与多回线.md)
|
package/docs/manual/09-/351/200/232/351/201/223/344/270/216/345/244/232/345/233/236/347/272/277.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## 通道与多回线
|
|
6
6
|
|
|
7
|
-
一个通道表示一条走廊里并行敷设的多条回线(二 / 三 / 四 / 五回线都行)。回线本身照常写进 `lines`,通道只描述它们怎么排布。通道两端可以绑在节点上:声明 `from` / `to` 之后,**两端必须有节点,通道才显示**——骨架的首尾顶点就是这两个节点的坐标,拖动节点整条通道跟着走,节点被删掉或设成 `visible: false`
|
|
7
|
+
一个通道表示一条走廊里并行敷设的多条回线(二 / 三 / 四 / 五回线都行)。回线本身照常写进 `lines`,通道只描述它们怎么排布。通道两端可以绑在节点上:声明 `from` / `to` 之后,**两端必须有节点,通道才显示**——骨架的首尾顶点就是这两个节点的坐标,拖动节点整条通道跟着走,节点被删掉或设成 `visible: false` 时通道与它的回线一起消失。写 `lineFollowsNode: false` 时例外:节点退场只影响节点,通道与回线继续停在最后一次解析出的骨架与宽度,见「筛选」与「配置项」。
|
|
8
8
|
|
|
9
9
|
### 通道显隐(visible)
|
|
10
10
|
|
|
@@ -161,11 +161,13 @@ console.log(view.getChannels()) // 骨架、每条回线的偏移与推导出来
|
|
|
161
161
|
|
|
162
162
|
两端锚定的通道还会把切点往节点里收一段:缺省按成员回线里最粗那条的线宽收(切点从节点边缘再往节点里挪一个线宽),所以线不会从节点边缘探出去;`options.channelTangentInset` 或单个通道的 `tangentInset` 可以改成固定的 CSS 像素(`0` 表示切点正好落在节点边上),和线宽一样会随相机缩放折算回世界单位。内收两侧合计最多吃掉节点宽度的 40%,小节点配粗线时不会把回线挤成一条;写成负数就是**外收**:切点从节点边缘往外让一段,整组回线比节点还宽,单侧最多让出节点宽度的 50%。
|
|
163
163
|
|
|
164
|
+
筛选只改变节点自身是否绘制,不改变仍显示的通道宽度:被筛掉的端点仍按 `points` 里的数据和同一条样式链取外框(点自身 > 规则 > `pointStyle`,含热力倍率),所以只筛掉一端时不会改按另一端尺寸算,两端都被筛掉时也不会退回 `width` / `channelWidth`。只有节点真被删除或写了 `visible: false` 时才按「没有节点」处理。
|
|
165
|
+
|
|
164
166
|
通道的配置项没有重复的,成对出现的都是「**全局默认 + 逐通道覆盖**」:`channelWidth` / `width`、`channelNodeWidth` / `nodeWidth`、`channelInset` / `inset`、`channelTangentInset` / `tangentInset`,单个通道不写就取 `options` 上的同名值;`groups` / `path` / `from` / `to` 分别管分组、骨架与两端锚定,各管一件事(`path` 是可选骨架,不写时由锚点或第一条回线补出)。要留意的是各自的**生效条件**(不是冗余,而是只在特定组合下才有意义):`offsetMode: 'tangent'`(默认)时 `inset` / `channelInset` 不参与计算;`nodeWidth` 不为 0 且两端都锚在节点上时 `width` 只作兜底(宽度按节点尺寸算,改它看不到变化);`tangentInset` 只对两端锚定的通道有效(没锚定时切点就是骨架端点,无所谓往哪收);只有一条回线的通道不排偏移(回线就是骨架),`nodeWidth` 与 `tangentInset` 对它的回线位置没有影响。
|
|
165
167
|
|
|
166
168
|
拐点挂在骨架上:`'parallel'` 模式下拖动通道内任一回线的拐点,整条通道的所有回线一起折线,回线之间保持平行等距;`'vertex'` 模式下只平移当前分组同一序号的拐点(见「分组拐点拖动模式」)。`insertWaypoint` / `removeWaypoint` 增删的也是骨架顶点(首尾两端由节点或原点决定,删不掉)。拐点只显示选中线路的规则对通道一样适用:通道内**任一回线被选中,整条通道的拐点都显示**,这样拖动时能看清整条走廊。拖动不做任何限制:拐点可以拖到两端节点之外、折回去、拐到任意一侧,拖动端点节点时中间拐点也保持原样,骨架怎么走回线就怎么平行偏移(`channelPathFor` 就是骨架的纯平行偏移)。`onWaypointChange` 载荷里的 `coordinate` 与 `line` 都是被操作的那条回线的最新几何(`line.path` 是推导后的折线);通道分组还要一起保存 `waypointOffsets`,只写 `line.path` 或只写公共 `path` 会丢掉 `'vertex'` 拖动结果。`getChannels()` 返回运行时状态:`{ id, channelId, channelIndex, lineIndexes, skeleton, waypointOffsets, offsets, paths, from, to, anchored, spacing }`——`anchored` 为 `true` 表示两端都落在节点上,`spacing` 是按两端节点尺寸算出来的相邻回线中心间距(分组之后 `offsets` 是这一组在整条通道里的那几条车道,`spacing` 仍是整条通道的间距),需要自有覆盖层或回写业务数据时用它。
|
|
167
169
|
|
|
168
|
-
|
|
170
|
+
两端锚定的通道与节点默认是联动的:拖动端点节点,骨架首尾跟着走(中间拐点保留),所有回线一起重算;节点被删掉或设成不可见时,通道与它的回线都从这一帧开始不参与渲染,节点回来后通道恢复,之前编辑过的拐点还在。`lineFollowsNode: false` 时只让节点退场,通道、回线与最后一份解析尺寸保持原样;节点仍在时拖动仍会实时更新通道几何。
|
|
169
171
|
|
|
170
172
|
### 通道分组
|
|
171
173
|
|
|
@@ -243,4 +245,6 @@ Demo 的「通道与数据」页直接接了两类假接口:通道分组拐点
|
|
|
243
245
|
|
|
244
246
|
---
|
|
245
247
|
|
|
248
|
+
**相关章节**:[03 配置项(options)](03-配置项.md) · [08 选中与拐点](08-选中与拐点.md) · [10 通道编辑与新增](10-通道编辑与新增.md) · [17 参数速查](17-参数速查.md)
|
|
249
|
+
|
|
246
250
|
[← 08 选中与拐点](08-选中与拐点.md) · [手册目录](../GisView.md) · [10 通道编辑与新增 →](10-通道编辑与新增.md)
|