gis-view-webgl2 0.1.1 → 0.1.2
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 +13 -1
- package/dist/gis-view.css +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +255 -3
- package/dist/index.js +1 -1
- package/docs/AI/345/257/271/350/257/235/346/261/207/346/200/273.md +65 -0
- package/docs/GisView.md +1 -1
- package/docs/ai/06-/344/274/232/350/257/235/347/264/242/345/274/225/344/270/216/345/244/215/346/237/245/346/226/271/346/263/225.md +58 -0
- package/docs/demos/ChannelDemo.vue +566 -6
- package/docs/demos/CopyMergeDemo.vue +57 -6
- package/docs/demos/LabelDemo.vue +67 -11
- package/docs/demos/api-index.js +13 -3
- package/docs/format/03-/346/213/220/347/202/271/350/243/205/351/245/260/344/270/216/346/240/267/345/274/217.md +4 -2
- package/docs/format/04-/351/200/232/351/201/223/344/270/216/346/240/207/347/255/276.md +5 -4
- package/docs/manual/02-/345/235/220/346/240/207/344/270/216/346/225/260/346/215/256.md +7 -2
- package/docs/manual/03-/351/205/215/347/275/256/351/241/271.md +21 -5
- package/docs/manual/06-/346/225/260/346/215/256/344/270/216/345/234/272/346/231/257/346/233/264/346/226/260.md +100 -0
- 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 +38 -0
- package/docs/manual/08-/351/200/211/344/270/255/344/270/216/346/213/220/347/202/271.md +5 -5
- package/docs/manual/09-/351/200/232/351/201/223/344/270/216/345/244/232/345/233/236/347/272/277.md +58 -8
- 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 +27 -2
- package/docs/manual/12-/346/240/207/347/255/276/344/270/216/350/243/205/351/245/260.md +45 -1
- package/docs/manual/16-/345/256/236/344/276/213/346/226/271/346/263/225/346/200/273/350/241/250.md +7 -1
- package/docs/manual/17-/345/217/202/346/225/260/351/200/237/346/237/245.md +8 -0
- package/docs/manual/18-/351/200/220/346/226/271/346/263/225/347/244/272/344/276/213.md +28 -0
- package/docs/manual/20-/346/200/247/350/203/275/344/270/216/345/244/247/346/225/260/346/215/256.md +3 -0
- 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 +1 -1
- package/docs/steps/README.md +8 -6
- package/docs/steps/selftest-demos.html +194 -29
- package/docs/steps/selftest-docs.html +7 -6
- package/docs/steps/selftest-features.html +213 -1
- package/docs/steps/selftest-labels.html +249 -4
- package/docs//346/216/245/345/217/243/345/215/217/350/256/256.md +17 -11
- package/package.json +2 -2
|
@@ -25,6 +25,7 @@ const copyItemsText = ref('—')
|
|
|
25
25
|
const copyLineChannelsText = ref('—')
|
|
26
26
|
const manualText = ref('—')
|
|
27
27
|
const mergeBackendText = ref('合并变更 → 后端事务:—')
|
|
28
|
+
const splitText = ref('拆分:先选中一个节点(不选就取第一个),再点拆分')
|
|
28
29
|
const copyBackendText = ref('复制落库:—')
|
|
29
30
|
const mergeSyncText = ref('合并落库:—')
|
|
30
31
|
const backendMode = ref('success')
|
|
@@ -64,6 +65,7 @@ let logSeq = 0
|
|
|
64
65
|
let copyRound = 0
|
|
65
66
|
let pasteRound = 0
|
|
66
67
|
let addPointRound = 0
|
|
68
|
+
let splitRound = 0
|
|
67
69
|
let mergeSyncTimer = null
|
|
68
70
|
let mergeSyncQueue = []
|
|
69
71
|
let disposed = false
|
|
@@ -735,7 +737,7 @@ const manualAddPointCopy = () => {
|
|
|
735
737
|
return manualText.value
|
|
736
738
|
}
|
|
737
739
|
|
|
738
|
-
const prepareMerge = () => {
|
|
740
|
+
const prepareMerge = () => {
|
|
739
741
|
if (!selectedPoints.value.length) selectBatchSources()
|
|
740
742
|
if (!mergeTargetOptions.value.some(item => item.value === mergeTargetId.value)) {
|
|
741
743
|
mergeTargetId.value = mergeTargetOptions.value[0]?.value ?? ''
|
|
@@ -743,8 +745,48 @@ const prepareMerge = () => {
|
|
|
743
745
|
refreshState()
|
|
744
746
|
actionText.value = `已准备 ${selectedPoints.value.length} 个选中节点;保留目标 ${mergeTargetId.value || '—'},可在画布继续 Ctrl 点选`
|
|
745
747
|
pushLog('merge/prepare', actionText.value)
|
|
746
|
-
return actionText.value
|
|
747
|
-
}
|
|
748
|
+
return actionText.value
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/** 节点拆分:把连在来源节点上的线路隔一条分给第二份,通道端点默认跟随成员线路 */
|
|
752
|
+
const splitSelectedPoint = () => {
|
|
753
|
+
const data = view?.getData()
|
|
754
|
+
if (!data?.points?.length) return '没有可拆分的节点'
|
|
755
|
+
const source = selectedPoints.value[0] ?? data.points[0]
|
|
756
|
+
const linked = data.lines
|
|
757
|
+
.map((line, index) => ({ line, index }))
|
|
758
|
+
.filter(({ line }) => String(line.from) === String(source.id) || String(line.to) === String(source.id))
|
|
759
|
+
const movedLines = linked.filter((_entry, index) => index % 2 === 1).map(entry => entry.line.id ?? entry.index)
|
|
760
|
+
splitRound += 1
|
|
761
|
+
const offset = 0.42 + splitRound * 0.04
|
|
762
|
+
const result = view.splitPoint(source.id, [
|
|
763
|
+
{
|
|
764
|
+
x: Number(source.x) - offset,
|
|
765
|
+
y: Number(source.y) - offset * 0.55,
|
|
766
|
+
name: `${pointLabel(source)} · A`,
|
|
767
|
+
zone_name: '拆分后 · A'
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
x: Number(source.x) + offset,
|
|
771
|
+
y: Number(source.y) + offset * 0.55,
|
|
772
|
+
name: `${pointLabel(source)} · B`,
|
|
773
|
+
zone_name: '拆分后 · B',
|
|
774
|
+
lines: movedLines
|
|
775
|
+
}
|
|
776
|
+
])
|
|
777
|
+
if (!result.ok) {
|
|
778
|
+
splitText.value = `拆分失败:${result.reason}`
|
|
779
|
+
actionText.value = splitText.value
|
|
780
|
+
pushLog('splitPoint', splitText.value)
|
|
781
|
+
return splitText.value
|
|
782
|
+
}
|
|
783
|
+
splitText.value = `splitPoint:${pointLabel(source)} → ${result.pointIds.join(' / ')} · 改线 ${result.linesChanged} / 删线 ${result.removedLines} · 改通道 ${result.channelsChanged} / 删通道 ${result.removedChannels} · 第 2 份接回线 ${movedLines.length} 条`
|
|
784
|
+
actionText.value = splitText.value
|
|
785
|
+
pushLog('splitPoint', splitText.value)
|
|
786
|
+
view.selectFeatures(result.pointIds)
|
|
787
|
+
refreshState()
|
|
788
|
+
return splitText.value
|
|
789
|
+
}
|
|
748
790
|
|
|
749
791
|
const mergePatch = () => {
|
|
750
792
|
const patch = {
|
|
@@ -879,6 +921,7 @@ const resetScene = () => {
|
|
|
879
921
|
copyText.value = '复制:—'
|
|
880
922
|
copyLineChannelsText.value = '—'
|
|
881
923
|
mergeBackendText.value = '合并变更 → 后端事务:—'
|
|
924
|
+
splitText.value = '拆分:先选中一个节点(不选就取第一个),再点拆分'
|
|
882
925
|
clipboardText.value = '剪贴板:—'
|
|
883
926
|
copyEventText.value = '还没有 pointCopy 事件'
|
|
884
927
|
copySourcesText.value = '—'
|
|
@@ -888,7 +931,8 @@ const resetScene = () => {
|
|
|
888
931
|
resetBackendDemo()
|
|
889
932
|
copyRound = 0
|
|
890
933
|
pasteRound = 0
|
|
891
|
-
addPointRound = 0
|
|
934
|
+
addPointRound = 0
|
|
935
|
+
splitRound = 0
|
|
892
936
|
refreshState()
|
|
893
937
|
actionText.value = `已恢复 ${fresh.points.length} 节点 / ${fresh.lines.length} 线路 / ${fresh.channels.length} 通道`
|
|
894
938
|
return actionText.value
|
|
@@ -1134,7 +1178,14 @@ onBeforeUnmount(() => {
|
|
|
1134
1178
|
<p class="dv-hint">mergeSelectedPoints 只并选中集;target 可以指定保留谁,item 只改最终节点的字段。拖点相撞走 pending / confirm 两站,确认前也能改写。合并落地后的 changes 可直接作为后端事务:删除来源节点、更新保留节点、更新 / 删除线路与通道。</p>
|
|
1135
1179
|
</div>
|
|
1136
1180
|
<div class="dv-group">
|
|
1137
|
-
<h3>4 ·
|
|
1181
|
+
<h3>4 · 拆分节点</h3>
|
|
1182
|
+
<div class="dv-row">
|
|
1183
|
+
<button type="button" class="dv-button dv-button--primary" data-demo="split-selected" @click="splitSelectedPoint">拆分选中节点</button>
|
|
1184
|
+
</div>
|
|
1185
|
+
<p class="dv-readout" data-demo="split-readout">{{ splitText }}</p>
|
|
1186
|
+
</div>
|
|
1187
|
+
<div class="dv-group">
|
|
1188
|
+
<h3>5 · 待确认合并</h3>
|
|
1138
1189
|
<p class="dv-readout" data-demo="merge-pending-readout">{{ pendingText }}</p>
|
|
1139
1190
|
<div class="dv-row cm-form">
|
|
1140
1191
|
<label>
|
|
@@ -1156,7 +1207,7 @@ onBeforeUnmount(() => {
|
|
|
1156
1207
|
<p class="dv-hint">清空选中后,把画布上的一个节点拖到另一个节点上松手;选保留拖动来源 / 碰撞目标,再点确认。pending 载荷的 impact 已按「保留碰撞目标」预演影响线路数,confirm 时按最终 keep 重算;名称、分区、电压和样式都随 item 写回最终节点。</p>
|
|
1157
1208
|
</div>
|
|
1158
1209
|
<div class="dv-group">
|
|
1159
|
-
<h3>
|
|
1210
|
+
<h3>6 · 复制 / 合并假接口<span class="dv-chip">{{ backendBusy ? '请求中' : '空闲' }}</span></h3>
|
|
1160
1211
|
<div class="dv-row cm-form">
|
|
1161
1212
|
<label>
|
|
1162
1213
|
下一次响应
|
package/docs/demos/LabelDemo.vue
CHANGED
|
@@ -101,8 +101,35 @@ const syncFormFromHit = () => {
|
|
|
101
101
|
nextTick(() => contentInput.value?.focus())
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
const buildOptions = () => ({
|
|
105
|
-
points: dataset.points,
|
|
104
|
+
const buildOptions = () => ({
|
|
105
|
+
points: dataset.points.map((point, index) => index === 0
|
|
106
|
+
? {
|
|
107
|
+
...point,
|
|
108
|
+
labels: [
|
|
109
|
+
{ id: 'default', hidden: true },
|
|
110
|
+
{
|
|
111
|
+
id: 'per-item-draggable',
|
|
112
|
+
content: '逐条 A · 可拖 / 可编辑',
|
|
113
|
+
position: 'top',
|
|
114
|
+
gap: 24,
|
|
115
|
+
draggable: true,
|
|
116
|
+
editable: true,
|
|
117
|
+
avoidOverlap: false,
|
|
118
|
+
style: { color: '#8ff0c4', fontSize: '12px' }
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: 'per-item-locked',
|
|
122
|
+
content: '逐条 B · 只读',
|
|
123
|
+
position: 'bottom',
|
|
124
|
+
gap: 24,
|
|
125
|
+
draggable: false,
|
|
126
|
+
editable: false,
|
|
127
|
+
avoidOverlap: false,
|
|
128
|
+
style: { color: '#ffb4c8', fontSize: '12px' }
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
: point),
|
|
106
133
|
lines: dataset.lines,
|
|
107
134
|
channels: dataset.channels,
|
|
108
135
|
channelWidth: 2.4,
|
|
@@ -134,10 +161,16 @@ const buildOptions = () => ({
|
|
|
134
161
|
editable: true,
|
|
135
162
|
style: { color: '#ffe08a', fontSize: '11px' }
|
|
136
163
|
},
|
|
137
|
-
onReady: () => {
|
|
138
|
-
emit('notice', `${dataset.points.length} 个节点 / ${dataset.channels.length} 条通道,标签可点可拖可右键`)
|
|
139
|
-
pushLog('ready', '视图就绪:点一下标签试试(右键还有菜单)')
|
|
140
|
-
|
|
164
|
+
onReady: () => {
|
|
165
|
+
emit('notice', `${dataset.points.length} 个节点 / ${dataset.channels.length} 条通道,标签可点可拖可右键`)
|
|
166
|
+
pushLog('ready', '视图就绪:点一下标签试试(右键还有菜单)')
|
|
167
|
+
const first = dataset.points[0]
|
|
168
|
+
const labels = view?.getLabels('point', first.id) ?? []
|
|
169
|
+
const perItem = labels.filter(label => label.id === 'per-item-draggable' || label.id === 'per-item-locked')
|
|
170
|
+
if (perItem.length) {
|
|
171
|
+
perItemText.value = `第一个节点有 ${perItem.length} 条逐条配置:${perItem.map(label => `${label.id}(${String(label.content)})`).join(' · ')};A 可拖可点,B 只读`
|
|
172
|
+
}
|
|
173
|
+
},
|
|
141
174
|
onSelect: () => syncSelection()
|
|
142
175
|
})
|
|
143
176
|
/* ---- 三条添加路径:统一 API 的三种 refs 写法 ---- */
|
|
@@ -164,7 +197,7 @@ const syncSelection = () => {
|
|
|
164
197
|
}
|
|
165
198
|
|
|
166
199
|
/** 面板上的「选中一个」:不用在画布上瞄,点一下就把第一条节点 / 线路交给选中集 */
|
|
167
|
-
const selectFirst = (kind) => {
|
|
200
|
+
const selectFirst = (kind) => {
|
|
168
201
|
const item = kind === 'line' ? view?.getData().lines?.[0] : view?.getData().points?.[0]
|
|
169
202
|
if (!item) {
|
|
170
203
|
return
|
|
@@ -173,8 +206,21 @@ const selectFirst = (kind) => {
|
|
|
173
206
|
labelKind.value = 'line'
|
|
174
207
|
}
|
|
175
208
|
view.selectFeatures([item.id])
|
|
176
|
-
pushLog('select', `用接口选中 ${item.id}`)
|
|
177
|
-
}
|
|
209
|
+
pushLog('select', `用接口选中 ${item.id}`)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/** 逐条交互示例:选中第一个节点并复读两条 labels 的定义来源 */
|
|
213
|
+
const focusPerItemLabels = () => {
|
|
214
|
+
const first = dataset.points[0]
|
|
215
|
+
if (!view || !first) return
|
|
216
|
+
view.selectFeatures([first.id])
|
|
217
|
+
const labels = view.getLabels('point', first.id) ?? []
|
|
218
|
+
const perItem = labels.filter(label => label.id === 'per-item-draggable' || label.id === 'per-item-locked')
|
|
219
|
+
perItemText.value = perItem.length
|
|
220
|
+
? `第一个节点 ${String(first.id)}:${perItem.map(label => `${label.id}(${String(label.content)})`).join(' · ')};A 可拖可点,B 只读`
|
|
221
|
+
: '逐条交互示例没有读出来'
|
|
222
|
+
pushLog('逐条标签', perItemText.value)
|
|
223
|
+
}
|
|
178
224
|
|
|
179
225
|
/** 记住这一批加出来的 labelId:批量改 / 批量删就动这一批(addOnce 每次写 备注1 / 备注2…) */
|
|
180
226
|
const rememberBatch = (result) => {
|
|
@@ -405,7 +451,8 @@ const describeChange = (payload) => {
|
|
|
405
451
|
* 标签覆盖读数(getLabelStates):一次列出「哪些标签被改过 / 拖过 / 隐藏过、哪些是运行时加的」,
|
|
406
452
|
* 不用自己拿 getLabels 逐条比对。labelChange 一响就刷新一次(批量加减改都在这一条路上)。
|
|
407
453
|
*/
|
|
408
|
-
const labelStatesText = ref('—')
|
|
454
|
+
const labelStatesText = ref('—')
|
|
455
|
+
const perItemText = ref('第一个节点有两条标签:A 可拖 / 可编辑,B 只读(不可拖 / 不可点)')
|
|
409
456
|
const syncLabelStates = () => {
|
|
410
457
|
const states = view?.getLabelStates() ?? []
|
|
411
458
|
if (!states.length) {
|
|
@@ -479,9 +526,18 @@ onBeforeUnmount(() => {
|
|
|
479
526
|
<p class="dv-hint">overlapMode: 'shift'(默认)撞上别的标签时先换落点;'hide' 撞上就直接不显示。两者都只在 labelOptimize: true 且 avoidOverlap 没关时生效。</p>
|
|
480
527
|
</div>
|
|
481
528
|
|
|
529
|
+
<div class="dv-group">
|
|
530
|
+
<h3>逐条配置可拖 / 可编辑</h3>
|
|
531
|
+
<div class="dv-row">
|
|
532
|
+
<button type="button" class="dv-button dv-button--primary" data-demo="label-per-item-focus" @click="focusPerItemLabels">选中第一个节点并查看两条标签</button>
|
|
533
|
+
</div>
|
|
534
|
+
<p class="dv-readout" data-demo="label-per-item-readout">{{ perItemText }}</p>
|
|
535
|
+
<p class="dv-hint">第一个节点的数据 labels 里写了两条:A 单条 draggable / editable 为 true,B 单条写 false。逐条配置覆盖全局 label 开关;直接拖 A、点 B 就能看出差别。</p>
|
|
536
|
+
</div>
|
|
537
|
+
|
|
482
538
|
<div class="dv-group">
|
|
483
539
|
<h3>
|
|
484
|
-
加标签(统一 API)
|
|
540
|
+
加标签(统一 API)
|
|
485
541
|
<span class="dv-chips">
|
|
486
542
|
<button
|
|
487
543
|
v-for="item in ['point', 'line']"
|
package/docs/demos/api-index.js
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* 源码或文档改过之后重跑一遍;`node docs/steps/check-doc-coverage.mjs` 会对账。
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
/** { members:
|
|
11
|
-
export const API_SUMMARY = {"members":
|
|
10
|
+
/** { members: 249, methods: 246, properties: 3, options: 92, sections: 16 } */
|
|
11
|
+
export const API_SUMMARY = {"members":249,"methods":246,"properties":3,"options":92,"sections":16}
|
|
12
12
|
|
|
13
13
|
/** 实例成员,按 docs/GisView.md「参数速查」的分组排 */
|
|
14
14
|
export const API_SECTIONS = [
|
|
@@ -114,6 +114,13 @@ export const API_SECTIONS = [
|
|
|
114
114
|
{ name: "getVisibleData", kind: "method", params: "无", returns: "GisViewData", doc: "过滤之后的数据副本(points / lines)", examples: [{"group":"坐标、拾取与读数","code":"// getVisibleData() / isPointVisible(index):筛选之后的整份数据 / 某个节点在不在图上\nconst visibleData = view.getVisibleData()\nconst shown = view.isPointVisible(0)\n","from":"header"}] },
|
|
115
115
|
{ name: "getMovedPoints", kind: "method", params: "无", returns: "GisViewMovedPoint[]:相对上次对账位置变过的节点(index / id / x / y / item),按 id 去重;被删掉的记录不在里面(顺手清掉)", doc: "位置对账:相对上次对账(建视图 / 整份换数据 / 上一次 clearMovedPoints)位置变过的节点,按 id 去重、一趟扫出 [{ index, id, x, y, item }] —— 拖动 / updatePoint / patchPoints / 撤销都算,removePoints 删掉的记录顺手清掉,见「节点位置对账」", examples: [{"group":"坐标、拾取与读数","code":"// getMovedPoints() / clearMovedPoints(refs?):位置对账 —— 相对上次对账哪些节点搬过位置\nconst movedPoints = view.getMovedPoints() // [{ index, id, x, y, item }]\nview.clearMovedPoints(movedPoints.map(one => one.id)) // 发完接口对账这批;不传 = 全部对账\n","from":"header"}] },
|
|
116
116
|
{ name: "clearMovedPoints", kind: "method", params: "refs?: GisViewFeatureRef | GisViewFeatureRef[] 记成新基准的节点(id / 下标 / { id } / { index },写法与 removePoints 一致);不传 / null 全部对账,空数组无操作", returns: "this", doc: "位置对账:把当前坐标记成新基准(发完接口告诉组件「这些已经同步过了」):不传 / null 全部对账,传一个或一批(写法与 removePoints 一致)只清这些,认不出来的跳过并记一条提醒;返回实例本身", examples: [{"group":"坐标、拾取与读数","code":"// getMovedPoints() / clearMovedPoints(refs?):位置对账 —— 相对上次对账哪些节点搬过位置\nconst movedPoints = view.getMovedPoints() // [{ index, id, x, y, item }]\nview.clearMovedPoints(movedPoints.map(one => one.id)) // 发完接口对账这批;不传 = 全部对账\n","from":"header"}] },
|
|
117
|
+
{ name: "getChangedChannels", kind: "method", params: "options?: GisViewChangedChannelOptions:reasons?: GisViewChangedChannelReason[] 只返回这些原因([] = 空表);ignoreGroups?: boolean 忽略分组新增 / 删除 / 重排,只比较共有分组的拐点", returns: "GisViewChangedChannel[]:相对上次通道对账变了哪些通道,每项给 { index, id, item, groups, groupsChanged, waypointsChanged, membersChanged, endpointsChanged, visibilityChanged, fieldsChanged, fields, reasons };筛选后 *Changed 标记与 fields 同步收窄,读本身不改基准", doc: "通道变化对账:相对上次对账(建视图 / 整份换通道声明 / 上一次 clearChangedChannels)成员、分组、拐点、端点、可见性或其余声明字段变过的通道。每项带当前 groups 快照、六个 *Changed 标记、fields 与 reasons;新加通道只补账不报变化,删掉的通道(含 removeLines 连带删除)从账本清掉。options.reasons 只取指定原因(空数组直接返回空表),options.ignoreGroups 忽略分组新增 / 删除 / 重排、仍报已有分组的拐点变化。节点拖动只改坐标、不改 from / to,因此不算端点变化;拖 / 加 / 删分组拐点会进 waypoints,见「通道变化对账」", examples: [{"group":"拐点与通道","code":"// getChangedChannels(options?) / clearChangedChannels(refs?):通道变化对账\nview.updateChannel('c1', { name: '东干线' })\nview.addChannelGroupWaypoint('c1', 'c1', [200, 120]) // 拐点变化入账(单组通道的组 id 就是通道 id)\nconst changedChannels = view.getChangedChannels() // [{ index, id, item, groups, reasons, … }]\nconsole.log(changedChannels[0]?.reasons) // ['waypoints'] / ['members'] / ['visibility']…\nconst waypointOnly = view.getChangedChannels({ reasons: ['waypoints'], ignoreGroups: true })\nview.clearChangedChannels('c1') // 发完接口对账这一条;不传 = 全部对账\n","from":"header"}] },
|
|
118
|
+
{ name: "clearChangedChannels", kind: "method", params: "refs?: GisViewFeatureRef | GisViewFeatureRef[] 记成新基准的通道(id / 下标 / { id } / { index },写法与 removePoints 一致);不传 / null 全部对账,空数组无操作", returns: "this", doc: "通道变化对账:把当前声明记成新基准(发完接口告诉组件「这些已经同步过了」):不传 / null 全部对账,传一个或一批(写法与 removePoints 一致)只清这些,认不出来的跳过并记一条提醒;返回实例本身", examples: [{"group":"拐点与通道","code":"// getChangedChannels(options?) / clearChangedChannels(refs?):通道变化对账\nview.updateChannel('c1', { name: '东干线' })\nview.addChannelGroupWaypoint('c1', 'c1', [200, 120]) // 拐点变化入账(单组通道的组 id 就是通道 id)\nconst changedChannels = view.getChangedChannels() // [{ index, id, item, groups, reasons, … }]\nconsole.log(changedChannels[0]?.reasons) // ['waypoints'] / ['members'] / ['visibility']…\nconst waypointOnly = view.getChangedChannels({ reasons: ['waypoints'], ignoreGroups: true })\nview.clearChangedChannels('c1') // 发完接口对账这一条;不传 = 全部对账\n","from":"header"}] },
|
|
119
|
+
{ name: "getChangedLines", kind: "method", params: "options?: GisViewChangedLineOptions:reasons?: GisViewChangedLineReason[] 只返回 path / endpoints / visibility / fields 中的指定原因([] = 空表)", returns: "GisViewChangedLine[]:相对上次线路对账变了哪些线路,每项给 { index, id, item, path, start, end, from, to, visible, pathChanged, endpointsChanged, visibilityChanged, fieldsChanged, fields, reasons };新加只补账、删除清账,读本身不改基准", doc: "线路变化对账:相对上次对账(建视图 / 整份换线路 / 上一次 clearChangedLines)path / start / end、from / to、可见性或其余声明字段变过的线路。每项带 { index, id, item, path, start, end, from, to, visible, pathChanged, endpointsChanged, visibilityChanged, fieldsChanged, fields, reasons };options.reasons 可写 path / endpoints / visibility / fields。新加线路只补账不报,删除线路(含 removeChannel 连带删除)同步清账;通道骨架变化不算线路变化,见「线路变化对账」", examples: [{"group":"拐点与通道","code":"// getChangedLines(options?) / clearChangedLines(refs?):只有节点和线路时也能独立对账\nview.updateLine('l1', { name: '东联络线' })\nconst changedLines = view.getChangedLines() // [{ index, id, item, path, from, to, reasons, … }]\nconsole.log(changedLines[0]?.reasons) // ['fields'] / ['path'] / ['endpoints'] / ['visibility']\nconst pathOnly = view.getChangedLines({ reasons: ['path'] })\nview.clearChangedLines('l1') // 发完接口对账这一条;不传 = 全部对账\n","from":"header"}] },
|
|
120
|
+
{ name: "clearChangedLines", kind: "method", params: "refs?: GisViewFeatureRef | GisViewFeatureRef[] 记成新基准的线路(写法与 removePoints 一致);不传 / null 全部对账,空数组无操作", returns: "this", doc: "线路变化对账:不传 / null 全部对账,传一个或一批(写法与 removePoints 一致)只清这些,空数组无操作;认不出来的跳过并记一条提醒,返回实例本身", examples: [{"group":"拐点与通道","code":"// getChangedLines(options?) / clearChangedLines(refs?):只有节点和线路时也能独立对账\nview.updateLine('l1', { name: '东联络线' })\nconst changedLines = view.getChangedLines() // [{ index, id, item, path, from, to, reasons, … }]\nconsole.log(changedLines[0]?.reasons) // ['fields'] / ['path'] / ['endpoints'] / ['visibility']\nconst pathOnly = view.getChangedLines({ reasons: ['path'] })\nview.clearChangedLines('l1') // 发完接口对账这一条;不传 = 全部对账\n","from":"header"}] },
|
|
121
|
+
{ name: "setFeatureVisible", kind: "method", params: "kind: GisViewVisibilityKind('point' / 'line' / 'channel');refs: GisViewVisibilityRefs 单个 / 一批 id 或下标,也认 'selection'(通道按选中回线的归属取整条);visible: boolean", returns: "GisViewSetVisibilityOutcome:{ ok, reason, kind, visible, indexes, ids, items, skipped };只改数据的 visible,整次调用一条历史、一条 batch 数据变更", doc: "统一隐藏 / 显示节点、线路或通道:只改数据里的 visible,不删要素,分组 / 拐点 / 编辑状态都保留。kind 收 point / line / channel,refs 收单个或一批 id / 下标 / { id } / { index },也认 'selection'(通道按选中回线的归属取整条);hideFeatures / showFeatures 是 false / true 的快捷写法。整次调用收成一条历史与一条 batch 数据变更,返回 { ok, reason, kind, visible, indexes, ids, items, skipped };认不出的引用逐条进 skipped,不影响其余条目", examples: [{"group":"配置与数据","code":"// setFeatureVisible(kind, refs, visible) / hideFeatures(kind, refs) / showFeatures(kind, refs):只改 visible,不删数据\nconst hiddenChannel = view.hideFeatures('channel', 'c1') // 'point' / 'line' / 'channel',refs 单个 / 数组 / 'selection'\nview.showFeatures('channel', 'c1') // 成员回线、分组、拐点原样回来\nview.setFeatureVisible('point', ['a', 'b'], false) // 一批节点一次收起(一条历史、一条 batch)\nconsole.log(hiddenChannel.ok, hiddenChannel.indexes, hiddenChannel.skipped)\n","from":"header"}] },
|
|
122
|
+
{ name: "hideFeatures", kind: "method", params: "同上,等价于 setFeatureVisible(kind, refs, false)", returns: "同上", doc: "统一隐藏 / 显示节点、线路或通道:只改数据里的 visible,不删要素,分组 / 拐点 / 编辑状态都保留。kind 收 point / line / channel,refs 收单个或一批 id / 下标 / { id } / { index },也认 'selection'(通道按选中回线的归属取整条);hideFeatures / showFeatures 是 false / true 的快捷写法。整次调用收成一条历史与一条 batch 数据变更,返回 { ok, reason, kind, visible, indexes, ids, items, skipped };认不出的引用逐条进 skipped,不影响其余条目", examples: [{"group":"配置与数据","code":"// setFeatureVisible(kind, refs, visible) / hideFeatures(kind, refs) / showFeatures(kind, refs):只改 visible,不删数据\nconst hiddenChannel = view.hideFeatures('channel', 'c1') // 'point' / 'line' / 'channel',refs 单个 / 数组 / 'selection'\nview.showFeatures('channel', 'c1') // 成员回线、分组、拐点原样回来\nview.setFeatureVisible('point', ['a', 'b'], false) // 一批节点一次收起(一条历史、一条 batch)\nconsole.log(hiddenChannel.ok, hiddenChannel.indexes, hiddenChannel.skipped)\n","from":"header"}] },
|
|
123
|
+
{ name: "showFeatures", kind: "method", params: "同上,等价于 setFeatureVisible(kind, refs, true)(隐藏后原样恢复)", returns: "同上", doc: "统一隐藏 / 显示节点、线路或通道:只改数据里的 visible,不删要素,分组 / 拐点 / 编辑状态都保留。kind 收 point / line / channel,refs 收单个或一批 id / 下标 / { id } / { index },也认 'selection'(通道按选中回线的归属取整条);hideFeatures / showFeatures 是 false / true 的快捷写法。整次调用收成一条历史与一条 batch 数据变更,返回 { ok, reason, kind, visible, indexes, ids, items, skipped };认不出的引用逐条进 skipped,不影响其余条目", examples: [{"group":"配置与数据","code":"// setFeatureVisible(kind, refs, visible) / hideFeatures(kind, refs) / showFeatures(kind, refs):只改 visible,不删数据\nconst hiddenChannel = view.hideFeatures('channel', 'c1') // 'point' / 'line' / 'channel',refs 单个 / 数组 / 'selection'\nview.showFeatures('channel', 'c1') // 成员回线、分组、拐点原样回来\nview.setFeatureVisible('point', ['a', 'b'], false) // 一批节点一次收起(一条历史、一条 batch)\nconsole.log(hiddenChannel.ok, hiddenChannel.indexes, hiddenChannel.skipped)\n","from":"header"}] },
|
|
117
124
|
{ name: "isPointVisible", kind: "method", params: "index: number 节点下标", returns: "boolean。在不在图上(被筛选 / visible: false 或发散渲染还没铺到的都算 false)", doc: "某个下标的节点当前在不在图上:被筛选 / visible: false 隐藏掉的不算,初始化发散渲染还没排到的那部分也不算", examples: [{"group":"坐标、拾取与读数","code":"// getVisibleData() / isPointVisible(index):筛选之后的整份数据 / 某个节点在不在图上\nconst visibleData = view.getVisibleData()\nconst shown = view.isPointVisible(0)\n","from":"header"}] },
|
|
118
125
|
{ name: "getElementBounds", kind: "method", params: "keys: GisViewFeatureKey[] 要素定位数组({ type, id } / { type, index } / 裸 id)", returns: "GisViewBounds | null", doc: "一批要素 GisViewFeatureKey[]({ type: 'point' | 'line', index },getSelections() 的结果可以直接传)的世界包围盒 { minX, minY, maxX, maxY };一个都没对上返回 null(数据已经换过)", examples: [{"group":"坐标、拾取与读数","code":"// getElementBounds(keys) / getViewState():一批要素的包围盒 / 一次取全视图读数\nconst box = view.getElementBounds(view.getSelections())\nconst state = view.getViewState()","from":"header"}] },
|
|
119
126
|
{ name: "getViewState", kind: "method", params: "无", returns: "GisViewViewState", doc: "一次取全的读数快照:camera / viewport / viewRect / layoutReady / selection / selectionIds / filter / filterResult / pointer / stats,自建状态栏与「布局铺好了没」的判断用它", examples: [{"group":"坐标、拾取与读数","code":"// getElementBounds(keys) / getViewState():一批要素的包围盒 / 一次取全视图读数\nconst box = view.getElementBounds(view.getSelections())\nconst state = view.getViewState()","from":"header"}] },
|
|
@@ -143,6 +150,7 @@ export const API_SECTIONS = [
|
|
|
143
150
|
{ name: "getPointClipboard", kind: "method", params: "无", returns: "GisViewClipboardItem | null", doc: "剪贴板:copyPointToClipboard 默认收当前选中的全部节点(只有没选中才回落到光标下的那个),copyPointsToClipboard 只认给定 / 选中的一批;Ctrl+V 时单节点且没有内部线路 / 通道仍走原预览,多节点或带线路 / 通道走整组落地,pastePoints 强制整组(单节点也走批量载荷)。getPointClipboard() 读 count / sources / items / lines / channels / anchor 快照,见「节点复制」", examples: [{"group":"选中、复制与合并","code":"// copyPoint(source?) / copyPoints(sources?, options?) / copySelectedPoints(options?) / copyPointToClipboard(sources?, options?) / copyPointsToClipboard(sources?, options?) / pastePoint(options?) / pastePoints(options?) / getPointClipboard()\nconst copyItem = view.copyPoint('a') // 一步到位,落在原位置旁边\nconst batchCopy = view.copyPoints(['a', 'b'], { select: true }) // 只复制这两个节点(不带未选中的线路 / 通道)\nconst selectedCopy = view.copySelectedPoints({ coordinate: [120, 80] }) // 复制当前选中集:节点 + 选中线路 / 通道\nview.copySelectedPoints({ withLines: true, withChannels: true }) // 恢复旧口径:来源内部线路 / 通道全带\nview.copyPoints(['a', 'b'], { lineIndexes: [0], channelIndexes: [1] }) // 再显式点名线路 / 通道\nview.copyPointToClipboard('a') // 收进剪贴板(默认整个选中集,Ctrl+C 的接口写法)\nview.copyPointsToClipboard(['a', 'b', 'c']) // 只把给定的一批收进剪贴板\nview.pastePoint({ screen: [320, 200] }) // 粘到光标处(Ctrl+V 的接口写法)\nview.pastePoint({ coordinate: [120, 80], offset: [40, 0] })\nconst pastedBatch = view.pastePoints({ coordinate: [160, 100] }) // 强制整组落地(单节点也走批量路)\nconsole.log(batchCopy.count, batchCopy.lines.length, selectedCopy.indexes, pastedBatch?.count)\nconst clipboard = view.getPointClipboard()\n","from":"header"}] },
|
|
144
151
|
{ name: "mergePoints", kind: "method", params: "source: GisViewPointRef 被并入的节点(并完就没了)、target: GisViewPointRef 接收的节点、options?: { originalEvent?: Event | null; item?: GisViewPoint }:item 可以给一份已经改好的合并结果(确认阶段改过 payload.item 之后就是它)", returns: "GisViewMergeOutcome", doc: "把来源节点并进目标节点(接口调用,不做确认):来源 / 目标收 id、下标或 { id } / { index },节点数据按 merge.createItem 合并(缺省目标优先、尺寸取双方最大、图标优先目标),改线路绑定、删自环 / 零长线 / 自环通道、把撞成同一条的通道合成一条,返回 { ok, item, linesChanged, removedLines, removedChannels, mergedChannels };并不了返回 ok: false 并另发一条失败事件,见「节点合并」", examples: [{"group":"选中、复制与合并","code":"// mergePoints(source, target, options?):把 source 并进 target(接口调用,不做确认)\nconst merged = view.mergePoints('a', 'b')\nconst mergedCustom = view.mergePoints('a', 'b', { item: { name: '合并结果', size: 12 } })\n","from":"header"}] },
|
|
145
152
|
{ name: "mergeSelectedPoints", kind: "method", params: "options: GisViewMergeSelectedOptions:target 指定并到哪一个(不给就自动挑绑定线路最多的);sources 直接给来源(不依赖选中集);item 是最终节点补丁或 (context) => 补丁(上下文含 item / merged / source / target / sourceIndex / targetIndex / merge / view;坐标与 id 仍按 target 保留);force: true 越过 mergeable: false;label / originalEvent", returns: "GisViewMergeSelectedOutcome", doc: "框选 / 多选之后一步把选中的节点并到一个目标上(接口调用):target 不指定就自动挑绑定线路最多的那一个(一样多取画得大的、再取下标小的),来源默认是除目标之外的选中节点、也可以用 sources(id / 下标 / { id } / { index },单个或数组)直接给 —— 这时不用先选中;mergeable: false 默认跳过(force: true 越过)、label 改这一步历史的标签。多个来源合成一步历史(数据变更收成一条 batch),返回 { phase: 'mergeSelected', ok, reason, target, merged, skipped, sourcesMerged, linesChanged, removedLines, removedChannels, mergedChannels, channelsChanged },见「节点合并」", examples: [{"group":"选中、复制与合并","code":"// mergeSelectedPoints(options?):框选 / 多选之后一次并完(目标缺省挑绑定线路最多的那个)\nconst mergedAll = view.mergeSelectedPoints()\nview.mergeSelectedPoints({ target: 'b', sources: ['a', 'c'], force: true })\n","from":"header"}] },
|
|
153
|
+
{ name: "splitPoint", kind: "method", params: "source: GisViewPointRef 要拆的节点;parts: GisViewSplitPointPart[] 至少两份,每份可直接写节点字段或放进 item,并用 lines / channels / channelFrom / channelTo 分配线路与通道端点;options?: GisViewSplitPointOptions:keepSourceId(缺省 true,第一份沿用来源 id)/ label", returns: "GisViewSplitPointOutcome:{ ok, reason, source, items, indexes, pointIds, linesChanged, removedLines, removedLineIds, removedLineIndexes, channelsChanged, removedChannels, removedChannelIds, skipped, changes };changes 可直接作为后端事务输入", doc: "mergePoints 的逆操作:把一个节点拆成两份或更多(第一份接在原下标上、缺省沿用原 id,其余追加到末尾),按每份的 item / 顶层字段生成新节点,按 lines 分配线路、按 channels / channelFrom / channelTo 分配受影响通道的两端。没显式分配的线路跟第一份;没显式分配的通道端点跟它第一条被分配过的成员回线。线路的 from / to 与和来源坐标重合的 start / end / path 顶点改到对应新节点;拆完后的自环 / 零长度线路与两端落到同一份的通道删掉,成员全没了的通道也删掉。整次调用只记一条历史、只发一条 splitPoint 数据变更,返回的 changes 可直接作为后端事务输入;至少两份、坐标必须有效、线路不能重复分配,写错时 ok: false 并在 reason 说明", examples: [{"group":"选中、复制与合并","code":"// splitPoint(source, parts, options?):把一个节点拆成多份(mergePoints 的逆操作)\nconst splitResult = view.splitPoint('a', [\n { x: 0, y: 0, name: '甲站(主)' }, // 第一份沿用原下标 / id\n { x: 80, y: 40, name: '甲站(东)', lines: ['l1'] } // 显式分给第二份;未分配的线路跟第一份\n], { label: '拆分甲站' })\nconsole.log(splitResult.pointIds, splitResult.linesChanged, splitResult.changes)\n","from":"header"}] },
|
|
146
154
|
{ name: "getPointMerge", kind: "method", params: "无(载荷带 impact:lineCount / linesChanged / removedLines / lineIds / removedLineIds 与通道读数,确认前就能估算影响)", returns: "GisViewPointMergePayload | null", doc: "读 / 裁决 / 收尾当前待确认的合并(把一个节点拖到另一个节点上之后):resolvePointMerge(true, { keep, item }) 推进到 confirm 阶段 —— keep 选保留碰撞目标(缺省)还是拖动的来源,item 改写最终节点的信息与样式,位置 / id 始终取保留端;resolvePointMerge(false) 让拖动的节点回原位。pending / confirm / getPointMerge() 的载荷带 impact(受影响线路条数、具体 lineIds 与通道读数;lineCount 按线路去重,linesChanged / removedLines 与落地结果同口径)。自己接管数据落地时用 commitPointMerge() 收状态、revertPointMerge() 还原(silent: true 不补发 cancel 载荷)", examples: [{"group":"选中、复制与合并","code":"// getPointMerge() / resolvePointMerge(confirmed?, options?) / commitPointMerge() / revertPointMerge()\nconst pendingMerge = view.getPointMerge() // 待确认的那一份载荷(没有就是 null)\nconsole.log(pendingMerge?.impact?.lineCount) // 这次合并会影响几条线路(改写 + 删除,按线路去重)\nconsole.log(pendingMerge?.impact?.lineIds) // 具体是哪几条(没有 id 时是 lines 下标)\nview.resolvePointMerge(true) // 确认(false = 取消)\nview.resolvePointMerge(true, { keep: 'source', item: { name: '合并结果', size: 18 } })\nview.resolvePointMerge(true, { keep: 'target', item: { color: '#2f6fd0', strokeColor: '#ffffff' } })\nview.resolvePointMerge(false) // 取消(拖动的节点回原位,数据不动)\nview.commitPointMerge() // 自己接管数据时收尾\nview.revertPointMerge() // 反悔(silent: true 时不补发 cancel 载荷)\n","from":"header"}] },
|
|
147
155
|
{ name: "resolvePointMerge", kind: "method", params: "confirmed?: boolean(缺省 true = 确认,false = 取消);options?: GisViewPointMergeConfirmOptions:keep 选 'target'(缺省,保留碰撞目标)/ 'source'(保留拖动的来源),item 是最终节点字段补丁(名称 / 分区 / 颜色 / 尺寸 / 图标 / 描边等;位置与 id 始终取保留端)", returns: "GisViewPointMergePayload | null", doc: "读 / 裁决 / 收尾当前待确认的合并(把一个节点拖到另一个节点上之后):resolvePointMerge(true, { keep, item }) 推进到 confirm 阶段 —— keep 选保留碰撞目标(缺省)还是拖动的来源,item 改写最终节点的信息与样式,位置 / id 始终取保留端;resolvePointMerge(false) 让拖动的节点回原位。pending / confirm / getPointMerge() 的载荷带 impact(受影响线路条数、具体 lineIds 与通道读数;lineCount 按线路去重,linesChanged / removedLines 与落地结果同口径)。自己接管数据落地时用 commitPointMerge() 收状态、revertPointMerge() 还原(silent: true 不补发 cancel 载荷)", examples: [{"group":"选中、复制与合并","code":"// getPointMerge() / resolvePointMerge(confirmed?, options?) / commitPointMerge() / revertPointMerge()\nconst pendingMerge = view.getPointMerge() // 待确认的那一份载荷(没有就是 null)\nconsole.log(pendingMerge?.impact?.lineCount) // 这次合并会影响几条线路(改写 + 删除,按线路去重)\nconsole.log(pendingMerge?.impact?.lineIds) // 具体是哪几条(没有 id 时是 lines 下标)\nview.resolvePointMerge(true) // 确认(false = 取消)\nview.resolvePointMerge(true, { keep: 'source', item: { name: '合并结果', size: 18 } })\nview.resolvePointMerge(true, { keep: 'target', item: { color: '#2f6fd0', strokeColor: '#ffffff' } })\nview.resolvePointMerge(false) // 取消(拖动的节点回原位,数据不动)\nview.commitPointMerge() // 自己接管数据时收尾\nview.revertPointMerge() // 反悔(silent: true 时不补发 cancel 载荷)\n","from":"header"}] },
|
|
148
156
|
{ name: "commitPointMerge", kind: "method", params: "无", returns: "boolean", doc: "读 / 裁决 / 收尾当前待确认的合并(把一个节点拖到另一个节点上之后):resolvePointMerge(true, { keep, item }) 推进到 confirm 阶段 —— keep 选保留碰撞目标(缺省)还是拖动的来源,item 改写最终节点的信息与样式,位置 / id 始终取保留端;resolvePointMerge(false) 让拖动的节点回原位。pending / confirm / getPointMerge() 的载荷带 impact(受影响线路条数、具体 lineIds 与通道读数;lineCount 按线路去重,linesChanged / removedLines 与落地结果同口径)。自己接管数据落地时用 commitPointMerge() 收状态、revertPointMerge() 还原(silent: true 不补发 cancel 载荷)", examples: [{"group":"选中、复制与合并","code":"// getPointMerge() / resolvePointMerge(confirmed?, options?) / commitPointMerge() / revertPointMerge()\nconst pendingMerge = view.getPointMerge() // 待确认的那一份载荷(没有就是 null)\nconsole.log(pendingMerge?.impact?.lineCount) // 这次合并会影响几条线路(改写 + 删除,按线路去重)\nconsole.log(pendingMerge?.impact?.lineIds) // 具体是哪几条(没有 id 时是 lines 下标)\nview.resolvePointMerge(true) // 确认(false = 取消)\nview.resolvePointMerge(true, { keep: 'source', item: { name: '合并结果', size: 18 } })\nview.resolvePointMerge(true, { keep: 'target', item: { color: '#2f6fd0', strokeColor: '#ffffff' } })\nview.resolvePointMerge(false) // 取消(拖动的节点回原位,数据不动)\nview.commitPointMerge() // 自己接管数据时收尾\nview.revertPointMerge() // 反悔(silent: true 时不补发 cancel 载荷)\n","from":"header"}] },
|
|
@@ -363,6 +371,7 @@ export const API_OPTIONS = [
|
|
|
363
371
|
{ name: "prebake", type: "GisViewPrebakeOptions | true", defaultValue: "关", doc: "贴图符号预热:把「这次画面会出现什么」提前告诉组件 —— 两种写法:combos 逐组合(精确,getSymbolCombos() 收出来的那份)/ symbols × pointColors × sizes 与 lineColors × 线路动画图标 全排列(省事,颜色与尺寸由同一个字段决定时会多烤很多)—— 第一帧之前就烤好,画到它们时命中的是现成的贴图(省掉解码 + 光栅化那一下);组合数与数据量无关,不配就是从前那条按需路径。读数 getPrebake() / getSymbolCombos()、手动再烤一遍 runPrebake(),见「贴图符号预热(prebake)」" },
|
|
364
372
|
{ name: "label", type: "GisViewLabelOptions | GisViewLabelOptions[]", defaultValue: "无", doc: "节点标签:内容 / 位置 / 显隐 / 避让 / 拖动与编辑都可配,写数组就是同一个节点上多条标签,与 lineLabel 共用一套避让网格,见「节点标签」" },
|
|
365
373
|
{ name: "labelOptimize", type: "boolean", defaultValue: "false", doc: "标签显示优化开关:缺省关 = 强制显示(不避让、不按 maxCount 截断、不设 scanLimit / 扫描预算,节点 / 线路的每个可见要素该出现的标签一条不少);写 true 与从前一致 —— 避让 / 换落点 / 数量上限 / 候选上限全部生效。标签订得密、数据量大(十万级)时建议打开,见「标签显示优化开关」" },
|
|
374
|
+
{ name: "labelRender", type: "'auto' | 'dom'", defaultValue: "'auto'", doc: "纯文本标签的容器渲染方式:auto 在强制显示档(labelOptimize 未开且未进密集档)下,同一层纯文本标签达到 1024 条时改画到一张 Canvas,不再逐条建 div;HTML / 元素内容 / 可拖拽 / 可编辑 / 超出 Canvas 样式能力的标签仍走 DOM。dom 始终逐条建 .gis-view__label。只影响容器,不改内容、锚点、显隐与 html 解析,见「标签容器渲染(labelRender)」" },
|
|
366
375
|
{ name: "lineLabel", type: "GisViewLineLabelOptions | GisViewLineLabelOptions[]", defaultValue: "无", doc: "线路标签:位置沿线走(比例 / 百分比 / 绝对距离),内容、避让、显隐都可配,与节点标签共用一套避让网格;写数组就是同一条线上多条标签,见「线路标签」" },
|
|
367
376
|
{ name: "labelStates", type: "GisViewLabelState[]", defaultValue: "无", doc: "标签的运行时状态(getLabelStates() 的那一份:拖出来的偏移、改过的内容与样式、运行时加的标签、隐藏覆盖):创建时喂回来就回显,等价于创建之后调 setLabelStates(states);updateOptions({ labelStates }) 同样认。exportData({ format: 'input' }) 的结果里就叫 labelStates,存档 → 回灌直接接上" },
|
|
368
377
|
{ name: "graphics", type: "GisViewGraphic[]", defaultValue: "无", doc: "与节点无关的扩展图形:按世界坐标放 SVG 路径 / 图片 / Canvas,支持锚点、偏移、旋转、透明度、zIndex 与 scaleWithView;位于画布之上、标签之下,运行时用 addGraphic / addGraphics / updateGraphic / removeGraphic / clearGraphics 增删改,见「扩展图形(graphic)」" },
|
|
@@ -390,7 +399,8 @@ export const API_OPTIONS = [
|
|
|
390
399
|
{ name: "selectionKinds", type: "GisViewSelectionKindsInput", defaultValue: "无(框选只收节点;Ctrl 多选收节点 / 线路 / 通道)", doc: "框选与 Ctrl / 多选点击的类型过滤:'point' 节点、'line' 通道外的独立线路、'channel' 通道回线;可写数组任意组合,'all' / true 全开,false / null 全关。通道回线只归 channel 管,通道外的线路只归 line 管;通道回线仍按 channelSelectMode 摊开。不写时保留旧口径;普通单选与 select / selectFeatures 不受它限制。运行时走 updateOptions({ selectionKinds }),见「框选」与「选择类型过滤」" },
|
|
391
400
|
{ name: "selectionBoxStyle", type: "GisViewSelectionBoxStyle", defaultValue: "蓝底 0.16 透明 + 1px 蓝框", doc: "框选矩形的填充与边框:fill、fillOpacity、stroke、strokeWidth" },
|
|
392
401
|
{ name: "selectionOnTop", type: "boolean", defaultValue: "true", doc: "选中的节点 / 拖动中的整组 / 待确认合并的目标节点,以及选中线路所在的整条通道,是否画在所有要素之上(与 zIndex 无关),见「选中 / 拖动的层级」" },
|
|
393
|
-
{ name: "channelSelectMode", type: "'line' | 'group' | 'channel'", defaultValue: "'line'", doc: "通道选中模式:点中通道里的一条回线时选中什么 —— 'line' 只选这一条、'group' 连它所在的分组一起、'channel'
|
|
402
|
+
{ name: "channelSelectMode", type: "'line' | 'group' | 'channel'", defaultValue: "'line'", doc: "通道选中模式:点中通道里的一条回线时选中什么 —— 'line' 只选这一条、'group' 连它所在的分组一起、'channel' 整条通道(所有分组的回线);通道以外的线路永远只选自己。普通点选与 Ctrl / ⌘ + 点击加点共用这一档高亮范围;Ctrl / ⌘ + 点击在 group / channel 下按整批取反;切换走 updateOptions({ channelSelectMode }),只重画一帧、不重排场景,见「通道选中模式」" },
|
|
403
|
+
{ name: "channelWaypointDragMode", type: "'parallel' | 'vertex'", defaultValue: "'parallel'", doc: "分组拐点拖动模式:'parallel' 沿用共用骨架 + 平行偏移(和原有逻辑一致),'vertex' 只平移当前分组同一 pathIndex 的拐点,其他拐点与分组不动;普通线路始终只动自己。vertex 的结果写进 groups[].waypointOffsets,切换走 updateOptions({ channelWaypointDragMode }),下一次拖动生效,见「分组拐点拖动模式」" },
|
|
394
404
|
{ name: "waypointEditable", type: "boolean", defaultValue: "false", doc: "是否允许编辑线路拐点(按住加点快捷键 shortcuts.addWaypoint(默认 Ctrl / ⌘)+ 点击添加、拖动移动、双击或删除快捷键删除),单条线可用 waypointEditable 覆盖;缺省关,写 waypointEditable: true 或 features: { waypoint: true } 才开。false(以及 features: { waypoint: false })会同时关闭新增、移动与删除,没有只关其中一项的细分开关;shortcuts.addWaypoint 仍只决定加点的组合键" },
|
|
395
405
|
{ name: "waypointVisibility", type: "'selected' | 'always'", defaultValue: "'selected'", doc: "拐点显示时机:selected 只显示选中线路(以及刚加过拐点的线路)的拐点,always 全部显示" },
|
|
396
406
|
{ name: "waypointStyle", type: "GisViewPointStyle", defaultValue: "无", doc: "拐点(线路 path 的中间顶点)的默认 / 选中样式,支持配置:字段与节点样式同款;缺省是白底蓝圈的 9px 圆点,waypointSelectStyle 没配时选中拐点用内置强调环,见「线路拐点」的「拐点样式」小节" },
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
| `lines[].path` | `GisViewCoordinate[]` | 这条线路的整条折线:首尾是端点(绑了 `from` / `to` 时取节点坐标),中间的点就是拐点。只有两端点时没有拐点 |
|
|
10
10
|
| `lines[].from` / `to` + `path` | `id` + `GisViewCoordinate[]` | 两端绑节点时 `path` 照样要写全(首尾两个顶点会被节点坐标替换):拖节点时端点跟着走,拐点一个都不动 |
|
|
11
11
|
| `channels[].path` / `channels[].groups[].path` | `GisViewCoordinate[]` | 通道**骨架**的中间拐点(两端由通道的 `from` / `to` 补齐):同一分组里的所有回线共用这一条骨架 |
|
|
12
|
+
| `channels[].groups[].waypointOffsets` | `Record<string, GisViewCoordinate>` | 分组刚性拐点偏移:键是含首尾端点的骨架顶点序号(只认中间拐点),值是组内所有回线在该顶点的世界坐标增量 |
|
|
12
13
|
|
|
13
14
|
**`path` 要写全**:线路的 `path` 是整条折线,首尾两个顶点给的是端点(绑了 `from` / `to` 时引擎用节点当前坐标替换它们),
|
|
14
15
|
**拐点 = 第 2 ~ n-1 个顶点**。只写中间那几个点会被首尾替换掉、直接退化成两端直连 —— 想要两个拐点就写成四个顶点;
|
|
@@ -23,7 +24,7 @@
|
|
|
23
24
|
|
|
24
25
|
两种写法在 `sample-waypoints.json` / `sample-channels.json` 里各有一份可以对着看。
|
|
25
26
|
|
|
26
|
-
**通道 /
|
|
27
|
+
**通道 / 分组的拐点存在公共骨架和分组偏移两层**:`channels[].path`(单组)与 `channels[].groups[].path`(多组)是整组共用的骨架中间拐点;`waypointOffsets` 只记 `channelWaypointDragMode: 'vertex'` 拖出来的按序号刚性增量。每条回线画出来的折线是“公共骨架 → 车道平行偏移 → 分组刚性偏移”之后的结果(只读,不回写)。读取时 `getChannelGroups(channelId)` 的 `path` / `skeleton` / `waypointOffsets` 是分组那一份,`getChannelGroupWaypoints(channelId, groupId)` 返回里的 `scope: 'group'` 说明这一点,`lines[].derived: true` 的 `path` / `waypoints` 才是各条回线偏移后的读数。偏移不写或为空对象就是普通平行骨架;切回 `'parallel'` 不会自动清掉已有偏移。
|
|
27
28
|
|
|
28
29
|
读写接口(都在实例方法里,逐要素改不改整份数据):
|
|
29
30
|
|
|
@@ -42,7 +43,8 @@
|
|
|
42
43
|
```js
|
|
43
44
|
view.exportData({ format: 'test', parts: ['waypoint'] })
|
|
44
45
|
// { parallel_groups: [{ group_id, member_line_ids, group_route: [[x, y], [拐点], …, [x, y]] }], counts, warnings }
|
|
45
|
-
// group_route
|
|
46
|
+
// group_route 含两端,中间就是拐点;有 waypointOffsets 时已经叠成实际路由
|
|
47
|
+
// 通道的每个分组各成一组,通道外的折线线路自己成一组
|
|
46
48
|
```
|
|
47
49
|
|
|
48
50
|
事件:`onWaypointChange` 的载荷给 `phase`(`add` / `remove` / `select` / `start` / `move` / `end`)、`lineIndex` / `pathIndex` / `coordinate`、
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
| `circuits` | `number` | `1` | 回线数量(`createChannels` 用它展开回线) |
|
|
13
13
|
| `lineIds` | `Array<string \| number>` | 无(`createChannels` 生成的那一份就是它) | 组成这条通道的线路 id,**顺序即回线顺序**(沿骨架左法线从负到正) |
|
|
14
14
|
| `path` | `GisViewCoordinate[]` | 无(两端直连) | 骨架的**中间拐点**(不含两端,两端由节点坐标补齐):与线路的 `path` 相反,这里只写中间 |
|
|
15
|
-
| `groups` | `GisViewChannelGroup[]` | 无(= 一个通道一组) | 分组声明:`[{ id, lineIds, path }]`,一组一条走廊;拆分 / 合并的结果写在这里,见「分组」 |
|
|
15
|
+
| `groups` | `GisViewChannelGroup[]` | 无(= 一个通道一组) | 分组声明:`[{ id, lineIds, path, waypointOffsets? }]`,一组一条走廊;拆分 / 合并的结果写在这里,见「分组」 |
|
|
16
16
|
| `width` / `offsetMode` / `inset` / `tangentInset` | `number` / `'tangent' \| 'inset'` / `number` / `number \| null` | 分别回落到 `options.channelWidth`(`0.02`)/ `'tangent'` / `options.channelInset`(`0`)/ `options.channelTangentInset`(`null` = 按回线线宽收) | 通道外观:宽度(`tangent` 下是最外侧两条回线的中心距)、偏移方式、内收比例(负数为外收)、两端切点内收 |
|
|
17
17
|
| `nodeWidth` | `number` | `options.channelNodeWidth`(`1`) | 「按两端节点尺寸取宽」的倍数:`1` = 回线正好铺在节点两边,`0` = 关掉自动取宽改用 `width` / `channelWidth` |
|
|
18
18
|
| `colors` / `lineWidth` / `opacity` | 数组 / 数字 | `options.colors`(`CHANNEL_DEFAULT_COLORS`)/ 无 / `1` | 回线的逐回颜色(不够时按顺序循环取)、线宽、透明度 |
|
|
@@ -29,9 +29,10 @@
|
|
|
29
29
|
- **成员池 = 顶层 `lineIds` + 只写在 `groups` 里的回线**(按分组顺序补在后面):车道顺序、「两端从第一条回线继承」与分组编辑(`splitChannelGroups` / `mergeChannelGroups` / `moveChannelLine` / `addChannelGroup`)都按这一份口径认成员。因此**只写 `groups`、完全不写顶层 `lineIds` 的通道也支持**:渲染照常,拆 / 并 / 挪分组、`removeLines` 收拾成员一样生效(`lineIds` 只列了一部分、其余只在 `groups` 里写的情况同理)。
|
|
30
30
|
- **往通道里加一条回线**:数据侧先有这条线(`lines[].id`)再写进 `lineIds` / `groups`;运行时用 `addChannelLines(channelId, lineIds)` 挂现成的线,或让 `updateChannel` 的第三段带着定义当场建 —— 认不出的成员 id 给了 `from` / `to`(两端都能在 `points` 里找到)、给了能用的 `path`,或这条通道自己声明了两端时就建(表单整份覆盖成员表走的这条路);`updateChannel` 的第四段 `lineIds` 是**整表对齐**:与第三段的线路数组一起给时,表里有、数据里没有的当场建,表里有的逐条改,表里没有了的旧成员直接从数据里删(视图跟着少);只传线路数组(不传第四段)就只改 id 匹配的成员、数量不动。移出用 `removeChannelLines`(留线)/ `removeLines`(删线)。
|
|
31
31
|
- **分组 id 在一条通道里要唯一**:id 是写回声明、按 id 指名分组的键(`moveChannelLine` / 选中 / 分组拐点读数都按它找组),两个组同名时只会认第一组。`addChannelGroup(..., { id })` 撞上已有分组时**返回 `ok: false`** 并说明(想并进去用 `moveChannelLine`);`splitChannelGroups` 这类不写 id 的入口按 `${通道 id}::N` 自动编号,不会撞名。
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
32
|
+
- 同一分组内的回线共用一条骨架:`parallel` 模式拖任一回线的拐点整组一起折,`vertex` 模式只移同组同一序号的拐点;两端节点、宽度、颜色这些配置仍由**通道**统管。
|
|
33
|
+
- **存的是公共骨架 + 分组偏移**:`groups[].path` 只有一条(整组共用),`groups[].waypointOffsets` 记 `vertex` 拖动按骨架序号产生的刚性增量;逐条回线各自的拐点不落数据 —— 加 / 删 / 拖只写这两层、按各条车道偏移推出来的是只读读数(`getChannelGroupWaypoints` 的 `scope: 'group'` / `lines[].derived`)。
|
|
34
|
+
- **`waypointOffsets` 的键按含首尾端点的骨架序号算**:只接受中间拐点,值可以是 `[dx, dy]` 或 `{ x, y }`;组内所有成员回线都叠这一份偏移。不写或写空对象是普通平行骨架,切回 `parallel` 不会自动清空;要清除就重写分组声明并带上当前 `path`、省略该项。
|
|
35
|
+
- 运行时读数:`getChannels()` 给**分组级**的一项(`{ id, channelId, channelIndex, lineIndexes, skeleton, waypointOffsets, offsets, paths, from, to, anchored, spacing }`,
|
|
35
36
|
一条通道拆成几组就有几项,`id` 是分组 id、`channelId` 才是通道 id);
|
|
36
37
|
`getChannelGroups(channelId)` 按通道 id 或通道定义 id 取该通道的全部分组,读数更细
|
|
37
38
|
(另给 `lineIds` / `lineCount` / `waypointCount` / `edited` / `current` 与可直接写回 `declaredPath` 的 `path`)。
|
|
@@ -183,6 +183,10 @@ createGisView(container, { points, lines }) // 不配 label / lineLabel 也画
|
|
|
183
183
|
| `visibility` | `'auto' \| 'always' \| 'hidden'` | 这一条的显隐策略 |
|
|
184
184
|
| `hidden` | `boolean` | 这一条不画(等于 `visibility: 'hidden'`;`removeLabel` 对声明里那一条落的覆盖就是它) |
|
|
185
185
|
| `parallel` | `boolean` | 线路标签:这一条是否跟着线路方向转 |
|
|
186
|
+
| `overlapMode` | `'shift' \| 'hide'` | 碰撞后的处理方式:换落点或直接不画;逐条覆盖全局的 `overlapMode` |
|
|
187
|
+
| `avoidOverlap` | `boolean` | 这一条是否参与避让;写 `false` 时即使全局开着避让也会画出来(`LabelDemo` 用它让两条标签同时出现) |
|
|
188
|
+
| `draggable` | `boolean` | 这一条能不能拖动;逐条覆盖 `options.label` / `options.lineLabel` 的 `draggable` |
|
|
189
|
+
| `editable` | `boolean` | 这一条能不能点选编辑;逐条覆盖 `options.label` / `options.lineLabel` 的 `editable`,写 `false` 时点击不触发 `labelClick` |
|
|
186
190
|
| `className` | `string` | 这一条的附加类名 |
|
|
187
191
|
| `added` | `boolean` | 这条是运行时加的(`addLabel`),持久化 / 整份回显时按它重建 |
|
|
188
192
|
|
|
@@ -231,8 +235,9 @@ const next = createGisView(el, {
|
|
|
231
235
|
| 字段 | 类型 | 说明 |
|
|
232
236
|
| --- | --- | --- |
|
|
233
237
|
| `id` | `string \| number` | 通道 id:同 id 的通道在数据刷新之间保留已编辑过的骨架 |
|
|
238
|
+
| `visible` | `boolean` | `false` 时整条通道与成员回线一起不画;数据、分组、拐点与编辑状态保留,改回 `true` 立即恢复 |
|
|
234
239
|
| `lineIds` | `Array<string \| number>` | 通道内的线路 id,**顺序就是回线顺序**(沿骨架左法线方向) |
|
|
235
|
-
| `groups` | `GisViewChannelGroup[]` | 分组声明:`{ id?, lineIds, path? }
|
|
240
|
+
| `groups` | `GisViewChannelGroup[]` | 分组声明:`{ id?, lineIds, path?, waypointOffsets? }`。缺省是「一个通道一组」;`waypointOffsets` 是 `vertex` 拖动按骨架序号记的刚性偏移 |
|
|
236
241
|
| `path` | `GisViewCoordinate[]` | 骨架的中间拐点(两端用 `from` / `to` 绑节点时只需写中间) |
|
|
237
242
|
| `from` / `to` | `string \| number` | 两端节点:声明了任意一端,两端就都必须落在节点上,节点不存在时整条通道与回线都不显示 |
|
|
238
243
|
| `width` | `number` | 通道宽度(覆盖 `channelWidth`),只在 `nodeWidth` 为 0 或两端没锚定时真正生效 |
|
|
@@ -243,7 +248,7 @@ const next = createGisView(el, {
|
|
|
243
248
|
| `tooltip` | `GisViewTooltipContent \| false` | 通道回线悬停时的提示内容(`{name}` 是通道名,`{circuits}` 是回数) |
|
|
244
249
|
| `cursor` / `ctrlCursor` | `GisViewCursorValue` | 悬停到这条通道回线上时的光标(回线自身也配了 `cursor` 时以回线为准) |
|
|
245
250
|
|
|
246
|
-
分组的语义:**一个通道默认一组**,拆分之后每组有自己的成员与拐点;加点 / 拖点只作用于同一分组,没列进任何分组的线路并回第一组。运行时读数用 `getChannelGroups()`,写回用 `groups[].path
|
|
251
|
+
分组的语义:**一个通道默认一组**,拆分之后每组有自己的成员与拐点;加点 / 拖点只作用于同一分组,没列进任何分组的线路并回第一组。运行时读数用 `getChannelGroups()`,写回用 `groups[].path`(它已经是「可以直接写回数据的中间拐点」)与 `waypointOffsets`(`vertex` 拖动的刚性偏移,键按含首尾端点的骨架序号算)。
|
|
247
252
|
|
|
248
253
|
### createChannels
|
|
249
254
|
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
| `prebake` | `GisViewPrebakeOptions \| true` | 关 | 贴图符号预热:把「这次画面会出现什么」提前告诉组件 —— 两种写法:`combos` 逐组合(精确,`getSymbolCombos()` 收出来的那份)/ `symbols × pointColors × sizes` 与 `lineColors × 线路动画图标` 全排列(省事,颜色与尺寸由同一个字段决定时会多烤很多)—— 第一帧之前就烤好,画到它们时命中的是现成的贴图(省掉解码 + 光栅化那一下);组合数与数据量无关,不配就是从前那条按需路径。读数 `getPrebake()` / `getSymbolCombos()`、手动再烤一遍 `runPrebake()`,见「贴图符号预热(prebake)」 |
|
|
38
38
|
| `label` | `GisViewLabelOptions \| GisViewLabelOptions[]` | 无 | 节点标签:内容 / 位置 / 显隐 / 避让 / 拖动与编辑都可配,**写数组就是同一个节点上多条标签**,与 `lineLabel` 共用一套避让网格,见「节点标签」 |
|
|
39
39
|
| `labelOptimize` | `boolean` | `false` | 标签显示优化开关:**缺省关 = 强制显示**(不避让、不按 `maxCount` 截断、不设 `scanLimit` / 扫描预算,节点 / 线路的每个可见要素该出现的标签一条不少);写 `true` 与从前一致 —— 避让 / 换落点 / 数量上限 / 候选上限全部生效。标签订得密、数据量大(十万级)时建议打开,见「标签显示优化开关」 |
|
|
40
|
+
| `labelRender` | `'auto' \| 'dom'` | `'auto'` | 纯文本标签的容器渲染方式:`auto` 在强制显示档(`labelOptimize` 未开且未进密集档)下,同一层纯文本标签达到 1024 条时改画到一张 Canvas,不再逐条建 `div`;HTML / 元素内容 / 可拖拽 / 可编辑 / 超出 Canvas 样式能力的标签仍走 DOM。`dom` 始终逐条建 `.gis-view__label`。只影响容器,不改内容、锚点、显隐与 `html` 解析,见「标签容器渲染(labelRender)」 |
|
|
40
41
|
| `lineLabel` | `GisViewLineLabelOptions \| GisViewLineLabelOptions[]` | 无 | 线路标签:位置沿线走(比例 / 百分比 / 绝对距离),内容、避让、显隐都可配,与节点标签共用一套避让网格;**写数组就是同一条线上多条标签**,见「线路标签」 |
|
|
41
42
|
| `labelStates` | `GisViewLabelState[]` | 无 | 标签的运行时状态(`getLabelStates()` 的那一份:拖出来的偏移、改过的内容与样式、运行时加的标签、隐藏覆盖):创建时喂回来就回显,等价于创建之后调 `setLabelStates(states)`;`updateOptions({ labelStates })` 同样认。`exportData({ format: 'input' })` 的结果里就叫 `labelStates`,存档 → 回灌直接接上 |
|
|
42
43
|
| `graphics` | `GisViewGraphic[]` | 无 | 与节点无关的扩展图形:按世界坐标放 SVG 路径 / 图片 / Canvas,支持锚点、偏移、旋转、透明度、`zIndex` 与 `scaleWithView`;位于画布之上、标签之下,运行时用 `addGraphic` / `addGraphics` / `updateGraphic` / `removeGraphic` / `clearGraphics` 增删改,见「扩展图形(graphic)」 |
|
|
@@ -57,7 +58,8 @@
|
|
|
57
58
|
| `selectionKinds` | `GisViewSelectionKindsInput` | 无(框选只收节点;Ctrl 多选收节点 / 线路 / 通道) | 框选与 Ctrl / 多选点击的类型过滤:`'point'` 节点、`'line'` 通道外的独立线路、`'channel'` 通道回线;可写数组任意组合,`'all'` / `true` 全开,`false` / `null` 全关。通道回线只归 `channel` 管,通道外的线路只归 `line` 管;通道回线仍按 `channelSelectMode` 摊开。不写时保留旧口径;普通单选与 `select` / `selectFeatures` 不受它限制。运行时走 `updateOptions({ selectionKinds })`,见「框选」与「选择类型过滤」 |
|
|
58
59
|
| `selectionBoxStyle` | `GisViewSelectionBoxStyle` | 蓝底 0.16 透明 + 1px 蓝框 | 框选矩形的填充与边框:`fill`、`fillOpacity`、`stroke`、`strokeWidth` |
|
|
59
60
|
| `selectionOnTop` | `boolean` | `true` | 选中的节点 / 拖动中的整组 / 待确认合并的目标节点,以及选中线路所在的整条通道,是否画在所有要素之上(与 `zIndex` 无关),见「选中 / 拖动的层级」 |
|
|
60
|
-
| `channelSelectMode` | `'line' \| 'group' \| 'channel'` | `'line'` | 通道选中模式:点中通道里的一条回线时选中什么 —— `'line'` 只选这一条、`'group'` 连它所在的分组一起、`'channel'`
|
|
61
|
+
| `channelSelectMode` | `'line' \| 'group' \| 'channel'` | `'line'` | 通道选中模式:点中通道里的一条回线时选中什么 —— `'line'` 只选这一条、`'group'` 连它所在的分组一起、`'channel'` 整条通道(所有分组的回线);通道以外的线路永远只选自己。普通点选与 Ctrl / ⌘ + 点击加点共用这一档高亮范围;Ctrl / ⌘ + 点击在 `group` / `channel` 下按整批取反;切换走 `updateOptions({ channelSelectMode })`,只重画一帧、不重排场景,见「通道选中模式」 |
|
|
62
|
+
| `channelWaypointDragMode` | `'parallel' \| 'vertex'` | `'parallel'` | 分组拐点拖动模式:`'parallel'` 沿用共用骨架 + 平行偏移(和原有逻辑一致),`'vertex'` 只平移当前分组同一 `pathIndex` 的拐点,其他拐点与分组不动;普通线路始终只动自己。`vertex` 的结果写进 `groups[].waypointOffsets`,切换走 `updateOptions({ channelWaypointDragMode })`,下一次拖动生效,见「分组拐点拖动模式」 |
|
|
61
63
|
| `waypointEditable` | `boolean` | `false` | 是否允许编辑线路拐点(按住加点快捷键 `shortcuts.addWaypoint`(默认 Ctrl / ⌘)+ 点击添加、拖动移动、双击或删除快捷键删除),单条线可用 `waypointEditable` 覆盖;**缺省关**,写 `waypointEditable: true` 或 `features: { waypoint: true }` 才开。`false`(以及 `features: { waypoint: false }`)会同时关闭新增、移动与删除,没有只关其中一项的细分开关;`shortcuts.addWaypoint` 仍只决定加点的组合键 |
|
|
62
64
|
| `waypointVisibility` | `'selected' \| 'always'` | `'selected'` | 拐点显示时机:`selected` 只显示选中线路(以及刚加过拐点的线路)的拐点,`always` 全部显示 |
|
|
63
65
|
| `waypointStyle` / `waypointSelectStyle` | `GisViewPointStyle` | 无 | 拐点(线路 `path` 的中间顶点)的默认 / 选中样式,**支持配置**:字段与节点样式同款;缺省是白底蓝圈的 9px 圆点,`waypointSelectStyle` 没配时选中拐点用内置强调环,见「线路拐点」的「拐点样式」小节 |
|
|
@@ -102,8 +104,8 @@
|
|
|
102
104
|
| --- | --- |
|
|
103
105
|
| 总开关与历史 | `features` · `history` |
|
|
104
106
|
| 数据与背景 | `points` · `lines` · `channels` · `background` |
|
|
105
|
-
| 通道几何 | `channelWidth` · `channelInset` · `channelNodeWidth` · `channelTangentInset` · `channelMaxGroups` · `channelGroupMaxLines` · `channelDraftStyle` · `channelSelectMode` |
|
|
106
|
-
| 样式与规则 | `pointStyle` · `lineStyle` · `pointRules` / `lineRules` · `heatmap` · `effects` · `lineDirection` · `prebake` · `label` · `labelOptimize` · `lineLabel` · `labelStates` · `tooltip` · `pointSizeScale` / `lineWidthScale`、`pointZoomScale` / `lineZoomScale`、`zoomBaseScale` · `cursorStyle` · `gridColor` · `gridSize` · `showGrid` |
|
|
107
|
+
| 通道几何 | `channelWidth` · `channelInset` · `channelNodeWidth` · `channelTangentInset` · `channelMaxGroups` · `channelGroupMaxLines` · `channelDraftStyle` · `channelSelectMode` · `channelWaypointDragMode` |
|
|
108
|
+
| 样式与规则 | `pointStyle` · `lineStyle` · `pointRules` / `lineRules` · `heatmap` · `effects` · `lineDirection` · `prebake` · `label` · `labelOptimize` · `labelRender` · `lineLabel` · `labelStates` · `tooltip` · `pointSizeScale` / `lineWidthScale`、`pointZoomScale` / `lineZoomScale`、`zoomBaseScale` · `cursorStyle` · `gridColor` · `gridSize` · `showGrid` |
|
|
107
109
|
| 状态样式与选中 | `pointHoverStyle` / `pointSelectStyle` · `lineHoverStyle` / `lineSelectStyle` · `pointMultiSelectStyle` / `pointBoxSelectStyle` · `lineMultiSelectStyle` · `defaultHighlight` · `selectionBoxStyle` · `selectionOnTop` · `waypointStyle` / `waypointSelectStyle` |
|
|
108
110
|
| 交互开关 | `boxSelect` · `multiSelect` · `waypointEditable` · `waypointVisibility` · `interactive` · `preventContextMenu` · `clickable` · `draggable` · `liveDrag` · `shortcuts` · `copy` · `remove` · `merge` |
|
|
109
111
|
| 视图与相机 | `minScale` / `maxScale` · `fitPadding` · `fitOnInit` · `initialView` · `zoomStep` |
|
|
@@ -178,7 +180,7 @@ const lines = [
|
|
|
178
180
|
|
|
179
181
|
- **类型**:`GisViewChannel[]`
|
|
180
182
|
- **默认值**:`[]`
|
|
181
|
-
- **说明**:通道:把若干条线路组织成并行敷设的多回线走廊,回线几何由骨架折线按偏移推导;两端可用 `from` / `to`
|
|
183
|
+
- **说明**:通道:把若干条线路组织成并行敷设的多回线走廊,回线几何由骨架折线按偏移推导;两端可用 `from` / `to` 绑在节点上,每条通道可写 `visible: false` 整条收起(成员回线、分组与拐点保留,改回 `true` 恢复)
|
|
182
184
|
- **示例**:
|
|
183
185
|
|
|
184
186
|
```js
|
|
@@ -263,9 +265,16 @@ view.updateOptions({ channelWidth: 0.08 }) // 没绑节点的那几条跟着
|
|
|
263
265
|
|
|
264
266
|
- **类型**:`'line' | 'group' | 'channel'`
|
|
265
267
|
- **默认值**:`'line'`
|
|
266
|
-
- **说明**:通道选中模式:点中通道里的一条回线时选中什么 —— `'line'` 只选这一条、`'group'` 连它所在的分组一起、`'channel'`
|
|
268
|
+
- **说明**:通道选中模式:点中通道里的一条回线时选中什么 —— `'line'` 只选这一条、`'group'` 连它所在的分组一起、`'channel'` 整条通道(所有分组的回线);通道以外的线路永远只选自己。普通点选与 Ctrl / ⌘ + 点击加点共用这一档高亮范围;Ctrl / ⌘ + 点击在 `group` / `channel` 下按整批取反;切换走 `updateOptions({ channelSelectMode })`,只重画一帧、不重排场景,见「通道选中模式」
|
|
267
269
|
- **参考**:见「通道选中模式(channelSelectMode)」一节,子字段在那里的表里逐个展开
|
|
268
270
|
|
|
271
|
+
#### `channelWaypointDragMode`
|
|
272
|
+
|
|
273
|
+
- **类型**:`'parallel' | 'vertex'`
|
|
274
|
+
- **默认值**:`'parallel'`
|
|
275
|
+
- **说明**:分组拐点拖动模式。`'parallel'` 沿用共用骨架 + 平行偏移,拖动时拐角处的相邻顶点可能随 miter 一起微调;`'vertex'` 只把当前分组同一 `pathIndex` 的拐点按相同世界增量平移,组内每条回线都跟着这个序号走,其他拐点与其它分组保持不动。普通线路不受这一项影响;`'vertex'` 的结果写进 `groups[].waypointOffsets`(键按含首尾端点的骨架序号算,只认中间拐点),切换走 `updateOptions({ channelWaypointDragMode })`,下一次拖动生效。切换模式不会清掉已有偏移;要恢复纯平行骨架,重写分组声明并带上当前 `path`、省略 `waypointOffsets`
|
|
276
|
+
- **参考**:见「分组拐点拖动模式(channelWaypointDragMode)」与「分组拐点:把某一组拉走」
|
|
277
|
+
|
|
269
278
|
### 样式与规则
|
|
270
279
|
|
|
271
280
|
#### `pointStyle`
|
|
@@ -377,6 +386,13 @@ view.updateOptions({ prebake: { combos: view.getSymbolCombos().combos } })
|
|
|
377
386
|
- **说明**:标签显示优化开关:**缺省关 = 强制显示**(不避让、不按 `maxCount` 截断、不设 `scanLimit` / 扫描预算,节点 / 线路的每个可见要素该出现的标签一条不少);写 `true` 与从前一致 —— 避让 / 换落点 / 数量上限 / 候选上限全部生效。标签订得密、数据量大(十万级)时建议打开,见「标签显示优化开关」
|
|
378
387
|
- **参考**:见「标签显示优化开关(labelOptimize)」一节,子字段在那里的表里逐个展开
|
|
379
388
|
|
|
389
|
+
#### `labelRender`
|
|
390
|
+
|
|
391
|
+
- **类型**:`'auto' | 'dom'`
|
|
392
|
+
- **默认值**:`'auto'`
|
|
393
|
+
- **说明**:纯文本标签的画法。`auto` 只在**强制显示档**(缺省 `labelOptimize: false` 且 `denseMode` 未激活)启用:节点层或线路层里可画布的纯文本标签达到 **1024** 条时,该层改用一张 Canvas,不再逐条建 `.gis-view__label`;`html: true`、函数返回 `HTMLElement`、可拖拽 / 可编辑,以及带 Canvas 不支持样式的标签仍保留 DOM。`dom` 始终走逐条 DOM,保持旧行为。它和 `html` 是两件事:`html` 只控制字符串按文本还是 HTML 解析,`html: false` 仍然会建 `div`;见「标签容器渲染(labelRender)」
|
|
394
|
+
- **参考**:见「标签容器渲染(labelRender)」一节
|
|
395
|
+
|
|
380
396
|
#### `lineLabel`
|
|
381
397
|
|
|
382
398
|
- **类型**:`GisViewLineLabelOptions | GisViewLineLabelOptions[]`
|