gis-view-webgl2 0.1.7 → 0.1.9
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 +14 -11
- package/dist/gis-view.css +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +445 -241
- package/dist/index.js +1 -1
- package/docs/AI/345/257/271/350/257/235/346/261/207/346/200/273.md +65 -498
- package/docs/GisView.md +1 -1
- package/docs/GisView/345/256/236/347/216/260/345/216/237/347/220/206.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 +114 -478
- package/docs/demos/BasicDemo.vue +144 -27
- package/docs/demos/BatchAddDemo.vue +133 -7
- package/docs/demos/ChannelDemo.vue +61 -0
- package/docs/demos/ConnectDemo.vue +164 -33
- package/docs/demos/CopyMergeDemo.vue +144 -42
- package/docs/demos/EventDemo.vue +29 -24
- package/docs/demos/LabelDemo.vue +5 -5
- package/docs/demos/api-index.js +53 -41
- package/docs/demos/gis-view-demo/GisViewDemoCardHeader.vue +1 -1
- package/docs/demos/gis-view-demo/GisViewDemoStage.vue +1 -1
- package/docs/demos/gis-view-demo/panels/DataPanels.vue +1 -1
- package/docs/demos/gis-view-demo/useGisViewDemo.js +31 -33
- package/docs/format/02-/350/212/202/347/202/271/344/270/216/347/272/277/350/267/257.md +1 -0
- package/docs/format/04-/351/200/232/351/201/223/344/270/216/346/240/207/347/255/276.md +3 -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 +8 -7
- package/docs/from0/05-/347/233/270/346/234/272/344/270/216/344/272/244/344/272/222.md +1 -1
- package/docs/from0/07-/351/200/232/351/201/223/345/210/206/347/273/204/344/270/216/345/244/232/345/233/236/347/272/277.md +26 -10
- package/docs/index.html +136 -13
- package/docs/internals/15-04-/351/200/220/350/275/256/350/256/260/345/275/225-/347/203/255/345/212/233/345/233/276/344/270/216/346/200/247/350/203/275.md +10 -0
- package/docs/manual/02-/345/235/220/346/240/207/344/270/216/346/225/260/346/215/256.md +1 -1
- package/docs/manual/03-/351/205/215/347/275/256/351/241/271.md +82 -14
- package/docs/manual/04-/344/272/213/344/273/266/344/270/216/345/233/236/350/260/203.md +23 -17
- package/docs/manual/05-/347/224/273/350/264/250/344/270/216/346/211/271/351/207/217/346/233/264/346/226/260.md +65 -0
- 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 +9 -10
- 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 +100 -40
- package/docs/manual/08-/351/200/211/344/270/255/344/270/216/346/213/220/347/202/271.md +11 -7
- package/docs/manual/09-/351/200/232/351/201/223/344/270/216/345/244/232/345/233/236/347/272/277.md +66 -6
- 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 +226 -493
- package/docs/manual/12-/346/240/207/347/255/276/344/270/216/350/243/205/351/245/260.md +28 -5
- package/docs/manual/14-/350/247/206/345/233/276/344/270/216/347/255/233/351/200/211.md +46 -14
- package/docs/manual/15-/345/257/274/345/207/272/344/270/216/351/233/206/346/210/220.md +5 -2
- package/docs/manual/16-/345/256/236/344/276/213/346/226/271/346/263/225/346/200/273/350/241/250.md +34 -29
- package/docs/manual/17-/345/217/202/346/225/260/351/200/237/346/237/245.md +30 -22
- package/docs/manual/18-/351/200/220/346/226/271/346/263/225/347/244/272/344/276/213.md +168 -81
- package/docs/manual/19-/350/257/273/346/225/260/344/270/216/346/213/226/346/213/275/351/242/204/350/247/210.md +1 -1
- package/docs/manual/20-/346/200/247/350/203/275/344/270/216/345/244/247/346/225/260/346/215/256.md +5 -3
- 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 +9 -6
- package/docs/steps/README.md +201 -120
- package/docs/steps/bench-scale.html +1 -1
- package/docs/steps/index.html +222 -6
- package/docs/steps/selftest-actions.html +26 -25
- package/docs/steps/selftest-data.html +1 -1
- package/docs/steps/selftest-demos.html +290 -16
- package/docs/steps/selftest-docs.html +17 -6
- package/docs/steps/selftest-features.html +594 -54
- package/docs/steps/selftest-full.html +3 -3
- package/docs/steps/selftest-labels.html +82 -1
- package/docs/steps/selftest-perf.html +62 -7
- package/docs/steps/selftest-select.html +71 -6
- package/docs/steps/step-05-pick.js +4 -8
- package/docs/steps/step-07-channels.js +3 -5
- package/docs/steps/step-08-labels.js +3 -3
- package/docs/steps/step-10-full.js +3 -3
- package/docs/steps/step-12-events.js +41 -24
- package/docs//344/273/2160/345/210/260/345/256/214/346/225/264/347/232/204/345/256/236/347/216/260.md +1 -0
- package/package.json +1 -1
- package/docs/ai/01-/350/265/267/346/272/220/344/270/216/350/277/231/344/273/275/346/261/207/346/200/273/347/232/204/347/224/261/346/235/245.md +0 -29
- package/docs/ai/02-/346/214/211/345/206/205/345/256/271/345/210/206/347/261/273-/350/277/231/344/270/200/350/267/257/351/203/275/345/234/250/346/224/271/344/273/200/344/271/210.md +0 -66
- package/docs/ai/03-/351/207/215/350/246/201/351/227/256/347/255/224/351/200/211/357/274/210/344/270/200/357/274/211/357/274/232/351/200/211/345/236/213/351/200/232/351/201/223/344/270/216/346/240/267/345/274/217.md +0 -178
- package/docs/ai/04-/351/207/215/350/246/201/351/227/256/347/255/224/351/200/211/357/274/210/344/272/214/357/274/211/357/274/232/344/272/244/344/272/222/346/200/247/350/203/275/344/270/216/346/225/260/346/215/256.md +0 -140
- package/docs/ai/05-/351/207/215/350/246/201/351/227/256/347/255/224/351/200/211/357/274/210/344/270/211/357/274/211/357/274/232/345/256/277/344/270/273/346/227/201/346/224/257/344/270/216/346/224/266/345/217/243.md +0 -43
package/docs/index.html
CHANGED
|
@@ -604,6 +604,95 @@
|
|
|
604
604
|
background: var(--accent);
|
|
605
605
|
color: #fff;
|
|
606
606
|
}
|
|
607
|
+
/* 正文顶部的文档位置:父文档可点,当前页只做层级提示 */
|
|
608
|
+
article .doc-breadcrumb {
|
|
609
|
+
display: flex;
|
|
610
|
+
flex-wrap: wrap;
|
|
611
|
+
gap: 5px 7px;
|
|
612
|
+
align-items: center;
|
|
613
|
+
margin: 0 0 13px;
|
|
614
|
+
color: var(--muted);
|
|
615
|
+
font-size: 12px;
|
|
616
|
+
line-height: 1.7;
|
|
617
|
+
}
|
|
618
|
+
article .doc-breadcrumb .slash {
|
|
619
|
+
color: var(--muted-2);
|
|
620
|
+
}
|
|
621
|
+
article .doc-breadcrumb a {
|
|
622
|
+
padding: 0;
|
|
623
|
+
border: 0;
|
|
624
|
+
color: var(--accent);
|
|
625
|
+
background: none;
|
|
626
|
+
text-decoration: none;
|
|
627
|
+
}
|
|
628
|
+
article .doc-breadcrumb a:hover {
|
|
629
|
+
color: var(--accent-strong);
|
|
630
|
+
border: 0;
|
|
631
|
+
background: none;
|
|
632
|
+
text-decoration: underline;
|
|
633
|
+
text-underline-offset: 3px;
|
|
634
|
+
}
|
|
635
|
+
article .doc-breadcrumb .current {
|
|
636
|
+
color: var(--text-strong);
|
|
637
|
+
font-weight: 600;
|
|
638
|
+
}
|
|
639
|
+
/* 文档末尾的上一份 / 下一份:沿侧栏顺序走,按钮本身就是可分享的深链 */
|
|
640
|
+
.doc-pager {
|
|
641
|
+
display: grid;
|
|
642
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
643
|
+
gap: 10px;
|
|
644
|
+
margin: 36px 0 0;
|
|
645
|
+
padding: 18px 0 0;
|
|
646
|
+
border-top: 1px solid var(--line-soft);
|
|
647
|
+
}
|
|
648
|
+
article a.doc-pager__link,
|
|
649
|
+
.doc-pager__empty {
|
|
650
|
+
display: flex;
|
|
651
|
+
flex-direction: column;
|
|
652
|
+
gap: 3px;
|
|
653
|
+
min-width: 0;
|
|
654
|
+
padding: 11px 13px;
|
|
655
|
+
border: 1px solid var(--line);
|
|
656
|
+
border-radius: 10px;
|
|
657
|
+
background: var(--surface-2);
|
|
658
|
+
color: var(--text);
|
|
659
|
+
text-decoration: none;
|
|
660
|
+
transition: border-color 0.14s, background 0.14s, box-shadow 0.14s;
|
|
661
|
+
}
|
|
662
|
+
article a.doc-pager__link:hover {
|
|
663
|
+
border-color: var(--accent-line);
|
|
664
|
+
background: var(--accent-soft);
|
|
665
|
+
color: var(--text);
|
|
666
|
+
box-shadow: var(--shadow-1);
|
|
667
|
+
}
|
|
668
|
+
.doc-pager__empty {
|
|
669
|
+
visibility: hidden;
|
|
670
|
+
}
|
|
671
|
+
.doc-pager .next {
|
|
672
|
+
grid-column: 2;
|
|
673
|
+
text-align: right;
|
|
674
|
+
}
|
|
675
|
+
.doc-pager small {
|
|
676
|
+
color: var(--accent);
|
|
677
|
+
font-size: 10.5px;
|
|
678
|
+
font-weight: 600;
|
|
679
|
+
letter-spacing: 0.08em;
|
|
680
|
+
}
|
|
681
|
+
.doc-pager b {
|
|
682
|
+
overflow: hidden;
|
|
683
|
+
color: var(--text-strong);
|
|
684
|
+
font-size: 13px;
|
|
685
|
+
text-overflow: ellipsis;
|
|
686
|
+
white-space: nowrap;
|
|
687
|
+
}
|
|
688
|
+
.doc-pager span {
|
|
689
|
+
overflow: hidden;
|
|
690
|
+
color: var(--muted);
|
|
691
|
+
font-size: 11.5px;
|
|
692
|
+
line-height: 1.55;
|
|
693
|
+
text-overflow: ellipsis;
|
|
694
|
+
white-space: nowrap;
|
|
695
|
+
}
|
|
607
696
|
/* README 首屏的推荐阅读路径:按任务给四条入口,不替代正文目录 */
|
|
608
697
|
.doc-paths {
|
|
609
698
|
margin: 0 0 22px;
|
|
@@ -629,7 +718,7 @@
|
|
|
629
718
|
}
|
|
630
719
|
.doc-paths__grid {
|
|
631
720
|
display: grid;
|
|
632
|
-
grid-template-columns: repeat(auto-fit, minmax(
|
|
721
|
+
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
|
633
722
|
gap: 9px;
|
|
634
723
|
}
|
|
635
724
|
article a.doc-path {
|
|
@@ -695,6 +784,15 @@
|
|
|
695
784
|
article a.doc-path {
|
|
696
785
|
min-height: 0;
|
|
697
786
|
}
|
|
787
|
+
.doc-pager {
|
|
788
|
+
grid-template-columns: minmax(0, 1fr);
|
|
789
|
+
}
|
|
790
|
+
.doc-pager .next {
|
|
791
|
+
grid-column: 1;
|
|
792
|
+
}
|
|
793
|
+
.doc-pager__empty {
|
|
794
|
+
display: none;
|
|
795
|
+
}
|
|
698
796
|
}
|
|
699
797
|
@keyframes fade-in {
|
|
700
798
|
from {
|
|
@@ -1296,7 +1394,7 @@
|
|
|
1296
1394
|
</aside>
|
|
1297
1395
|
<article id="content"><p id="loading">正在读取…</p></article>
|
|
1298
1396
|
<aside id="toc">
|
|
1299
|
-
<h2
|
|
1397
|
+
<h2>本页目录<span class=count id=toc-count></span></h2>
|
|
1300
1398
|
<nav></nav>
|
|
1301
1399
|
</aside>
|
|
1302
1400
|
</div>
|
|
@@ -1323,7 +1421,7 @@
|
|
|
1323
1421
|
{ file: 'manual/14-视图与筛选.md', title: '手册 14 · 视图与筛选', blurb: '筛选 / 搜索 / 视图与背景', parent: 'GisView.md' },
|
|
1324
1422
|
{ file: 'manual/15-导出与集成.md', title: '手册 15 · 导出与集成', blurb: '导出 / 插件 / 自建界面', parent: 'GisView.md' },
|
|
1325
1423
|
{ file: 'manual/16-实例方法总表.md', title: '手册 16 · 实例方法总表', blurb: '实例方法主表', parent: 'GisView.md' },
|
|
1326
|
-
{ file: 'manual/17-参数速查.md', title: '手册 17 · 参数速查', blurb: '
|
|
1424
|
+
{ file: 'manual/17-参数速查.md', title: '手册 17 · 参数速查', blurb: '273 个成员逐个列全', parent: 'GisView.md' },
|
|
1327
1425
|
{ file: 'manual/18-逐方法示例.md', title: '手册 18 · 逐方法示例', blurb: '每个成员一段示例', parent: 'GisView.md' },
|
|
1328
1426
|
{ file: 'manual/19-读数与拖拽预览.md', title: '手册 19 · 读数与拖拽预览', blurb: '读数 / 定位 / 落点预览', parent: 'GisView.md' },
|
|
1329
1427
|
{ file: 'manual/20-性能与大数据.md', title: '手册 20 · 性能与大数据', blurb: '大数据开关与实测', parent: 'GisView.md' },
|
|
@@ -1362,13 +1460,8 @@
|
|
|
1362
1460
|
{ file: 'internals/16-03-优化与取舍-下.md', title: '原理 16-03 · 优化与取舍(下)', blurb: '16.57 ~ 16.74:坐标、通道、筛选与文档口径的取舍。', parent: 'GisView实现原理.md' },
|
|
1363
1461
|
{ file: 'internals/17-调试与扩展建议.md', title: '原理 17 · 调试与扩展建议', blurb: '怎么排查 GL 错误、怎么接自己的覆盖层与插件。', parent: 'GisView实现原理.md' },
|
|
1364
1462
|
{ file: 'internals/18-性能实测与WebGPU评估.md', title: '原理 18 · 性能实测与 WebGPU 评估', blurb: '十五轮实测数据、瓶颈定位与 WebGPU 值不值得上。', parent: 'GisView实现原理.md' },
|
|
1365
|
-
{ file: 'AI对话汇总.md', title: 'AI
|
|
1366
|
-
{ file: 'ai/
|
|
1367
|
-
{ file: 'ai/02-按内容分类-这一路都在改什么.md', title: '对话 02 按内容分类:这一路都在改什么', blurb: '七个主题(通道分组拐点 / 交互编辑 / 样式视觉 / 性能 / 数据接口 / 文档工程 /', parent: 'AI对话汇总.md' },
|
|
1368
|
-
{ file: 'ai/03-重要问答选(一):选型通道与样式.md', title: '对话 03 重要问答选(一):选型、通道与样式', blurb: '选型 13 问、立项、通道诞生、缩放 / 筛选 / 搜索的成形、颜色语义(描边 vs 填充)', parent: 'AI对话汇总.md' },
|
|
1369
|
-
{ file: 'ai/04-重要问答选(二):交互性能与数据.md', title: '对话 04 重要问答选(二):交互、性能与数据', blurb: '功能开关与按总量付费的循环、节点拖拽一闪一闪、线路批次视口裁剪、百万级解析、以及 20 条的', parent: 'AI对话汇总.md' },
|
|
1370
|
-
{ file: 'ai/05-重要问答选(三):宿主旁支与收口.md', title: '对话 05 重要问答选(三):宿主旁支与收口', blurb: '宿主 SVG / 直流标记不画的排查、选中集与拐点键跟着要素走、以及最近一轮的六条问题。', parent: 'AI对话汇总.md' },
|
|
1371
|
-
{ file: 'ai/06-会话索引与复查方法.md', title: '对话 06 会话索引与复查方法', blurb: '39 个会话的索引表(时间 / 会话文件 / 轮数 / 这一轮做了什么)与「怎么自己复查」。', parent: 'AI对话汇总.md' },
|
|
1463
|
+
{ file: 'AI对话汇总.md', title: 'AI 对话汇总', blurb: '39 个会话、194 轮:关键决策 / 精选问答 / 演进时间线', groupLabel: '维护索引 1 份' },
|
|
1464
|
+
{ file: 'ai/06-会话索引与复查方法.md', title: '维护索引与复查', blurb: '会话文件 / 历史增量 / 当前轮次 / 自测命令', parent: 'AI对话汇总.md' },
|
|
1372
1465
|
{ file: '从0到完整的实现.md', title: '从 0 到完整的实现(索引)', blurb: '分步实现讲义(配 steps 里的 demo)', groupLabel: '15 份' },
|
|
1373
1466
|
{ file: 'from0/01-先把地图想清楚.md', title: '讲义 01 先把地图想清楚', blurb: '三层结构、四种坐标、GeoJSON 底图上的真实经纬度与文件职责。', parent: '从0到完整的实现.md' },
|
|
1374
1467
|
{ file: 'from0/02-WebGL2起步.md', title: '讲义 02 WebGL2 起步', blurb: '拿上下文、写着色器、那 9 个浮点数、混合与尺寸跟随。', parent: '从0到完整的实现.md' },
|
|
@@ -1385,7 +1478,7 @@
|
|
|
1385
1478
|
{ file: 'from0/13-从零搭一整套-上.md', title: '讲义 13 从零搭一整套(上)', blurb: '目标与文件、起工程,以及第 1 ~ 5 步的完整代码(常量 / 上下文 / 相机 / 解析 ', parent: '从0到完整的实现.md' },
|
|
1386
1479
|
{ file: 'from0/14-从零搭一整套-下.md', title: '讲义 14 从零搭一整套(下)', blurb: '第 6 ~ 7 步(拾取交互、尺寸与对外接口)、验收清单与往完整库长。', parent: '从0到完整的实现.md' },
|
|
1387
1480
|
{ file: 'from0/15-附录-常量速查与踩坑清单.md', title: '讲义 15 附录:常量速查与踩坑清单', blurb: '常量速查表与 27 条踩坑记录。', parent: '从0到完整的实现.md' },
|
|
1388
|
-
{ file: 'steps/README.md', title: 'steps/README.md(分步 demo
|
|
1481
|
+
{ file: 'steps/README.md', title: 'steps/README.md(分步 demo 教学路线)', blurb: '四段新手路线、每步验收、搭建思路与优化顺序', groupLabel: '逐轮记录 10 份' },
|
|
1389
1482
|
{ file: 'steps/rounds/README.md', title: '逐轮记录(索引)', blurb: '93 轮「修改.txt / 问题.txt」的落点表,按时间分页', parent: 'steps/README.md' },
|
|
1390
1483
|
{ file: 'steps/rounds/01-第1-11轮.md', title: '逐轮 第 1 ~ 11 轮', blurb: '这 11 轮各改了什么、需求落在哪(新的在后一页)。想看某一轮的完整实测与设计取舍,再翻《实', parent: 'steps/README.md' },
|
|
1391
1484
|
{ file: 'steps/rounds/02-第12-22轮.md', title: '逐轮 第 12 ~ 22 轮', blurb: '这 11 轮各改了什么、需求落在哪(新的在后一页)。想看某一轮的完整实测与设计取舍,再翻《实', parent: 'steps/README.md' },
|
|
@@ -1399,7 +1492,7 @@
|
|
|
1399
1492
|
{ file: '../src/gis-view/README.md', title: 'src/gis-view/README.md', blurb: '源码导读与逐轮实现记录' }
|
|
1400
1493
|
]
|
|
1401
1494
|
const PAGES = [
|
|
1402
|
-
{ href: 'api/index.html', title: 'API 速查(方法 + 示例)', blurb: '
|
|
1495
|
+
{ href: 'api/index.html', title: 'API 速查(方法 + 示例)', blurb: '273 个实例成员 / 100 个 options,逐个带示例与复制' },
|
|
1403
1496
|
{ href: 'playground/index.html', title: '调试演示页(粘代码就跑)', blurb: '左侧编辑、右侧真实实例 + GeoJSON 底图:内置示例与「这一份文档」的示例同在一个下拉,粘代码直接跑' },
|
|
1404
1497
|
{ href: 'guide/sample-document.html', title: 'sample-document.json 图解', blurb: '点数据看端点 / 拐点 / 分组骨架' },
|
|
1405
1498
|
{ href: 'steps/index.html', title: '从 0 手写分步 demo', blurb: '13 步,每步一个文件' },
|
|
@@ -1665,6 +1758,7 @@
|
|
|
1665
1758
|
const pageListEl = document.querySelector('#page-list')
|
|
1666
1759
|
const content = document.querySelector('#content')
|
|
1667
1760
|
const tocNav = document.querySelector('#toc nav')
|
|
1761
|
+
const tocCount = document.querySelector('#toc-count')
|
|
1668
1762
|
/** 左侧每组子文档的折叠状态:按父文档文件名记,刷新 / 切文档都保持(全部收起之后仍能在当前组里点开) */
|
|
1669
1763
|
const SIDEBAR_GROUPS_KEY = 'gisDocs.closedGroups'
|
|
1670
1764
|
const closedSidebarGroups = new Set()
|
|
@@ -1726,6 +1820,30 @@
|
|
|
1726
1820
|
* 父条目自己的 blurb 仍在行内;`groupLabel` 是那行「手册 21 章」这样的分组标题。
|
|
1727
1821
|
* 过滤时父 / 子各按标题匹配:命中父就整组留着,只命中子就只留命中的那几份。
|
|
1728
1822
|
*/
|
|
1823
|
+
const shortDocTitle = title => String(title ?? '').replace(/\s*[((]索引[))]\s*$/, '')
|
|
1824
|
+
const renderBreadcrumb = doc => {
|
|
1825
|
+
const parent = doc.parent ? DOCS.find(item => item.file === doc.parent) : null
|
|
1826
|
+
const parts = ['<span>文档中心</span>']
|
|
1827
|
+
if (parent) {
|
|
1828
|
+
parts.push(`<a href='#${encodeURIComponent(parent.file)}' data-doc='${escapeHtml(parent.file)}'>${escapeHtml(shortDocTitle(parent.title))}</a>`)
|
|
1829
|
+
}
|
|
1830
|
+
parts.push(`<span class='current' aria-current='page'>${escapeHtml(shortDocTitle(doc.title))}</span>`)
|
|
1831
|
+
return `<nav class='doc-breadcrumb' aria-label='文档位置'>${parts.join('<span class=slash>/</span>')}</nav>`
|
|
1832
|
+
}
|
|
1833
|
+
const renderDocPager = file => {
|
|
1834
|
+
const at = DOCS.findIndex(item => item.file === file)
|
|
1835
|
+
if (at < 0) {
|
|
1836
|
+
return ''
|
|
1837
|
+
}
|
|
1838
|
+
const pagerItem = (doc, direction) => {
|
|
1839
|
+
if (!doc) {
|
|
1840
|
+
return `<span class='doc-pager__empty ${direction}' aria-hidden='true'></span>`
|
|
1841
|
+
}
|
|
1842
|
+
const label = direction === 'prev' ? '← 上一份' : '下一份 →'
|
|
1843
|
+
return `<a class='doc-pager__link ${direction}' href='#${encodeURIComponent(doc.file)}' data-doc='${escapeHtml(doc.file)}'><small>${label}</small><b>${escapeHtml(shortDocTitle(doc.title))}</b><span>${escapeHtml(doc.blurb)}</span></a>`
|
|
1844
|
+
}
|
|
1845
|
+
return `<nav class='doc-pager' aria-label='相邻文档'>${pagerItem(DOCS[at - 1], 'prev')}${pagerItem(DOCS[at + 1], 'next')}</nav>`
|
|
1846
|
+
}
|
|
1729
1847
|
const renderSidebar = (filter = '') => {
|
|
1730
1848
|
const keyword = filter.toLowerCase()
|
|
1731
1849
|
const match = doc => !keyword || doc.title.toLowerCase().includes(keyword)
|
|
@@ -1956,7 +2074,7 @@
|
|
|
1956
2074
|
{ badge: 'START', title: '第一次使用', desc: '引入、最小数据与首屏配置,先把图画出来。', meta: '01 快速开始 · 约 10 分钟', file: 'manual/01-快速开始.md' },
|
|
1957
2075
|
{ badge: 'BACKEND', title: '接后端与导出', desc: '编辑接口、导出回灌、插件与自建界面。', meta: '15 导出与集成', file: 'manual/15-导出与集成.md' },
|
|
1958
2076
|
{ badge: 'PERF', title: '十万级性能', desc: 'Worker 筛选 / 异步搜索、批量更新与质量档。', meta: '20 性能与大数据', file: 'manual/20-性能与大数据.md' },
|
|
1959
|
-
{ badge: 'API', title: '查方法与参数', desc: '实例方法、options 与可复制示例集中检索。', meta: 'API 速查 ·
|
|
2077
|
+
{ badge: 'API', title: '查方法与参数', desc: '实例方法、options 与可复制示例集中检索。', meta: 'API 速查 · 273 个成员', href: 'api/index.html', external: true }
|
|
1960
2078
|
]
|
|
1961
2079
|
const renderReadingPaths = () => `<section class='doc-paths' aria-label='推荐阅读路径'>` +
|
|
1962
2080
|
`<div class='doc-paths__head'><strong>按任务选一条阅读路径</strong><span>第一次进来先看快速开始;带着明确目标时直接跳到对应章节。</span></div>` +
|
|
@@ -2007,6 +2125,11 @@
|
|
|
2007
2125
|
syncHash(node.dataset.slug ?? '')
|
|
2008
2126
|
})
|
|
2009
2127
|
})
|
|
2128
|
+
content.insertAdjacentHTML('afterbegin', renderBreadcrumb(target))
|
|
2129
|
+
content.insertAdjacentHTML('beforeend', renderDocPager(target.file))
|
|
2130
|
+
if (tocCount) {
|
|
2131
|
+
tocCount.textContent = String(toc.length)
|
|
2132
|
+
}
|
|
2010
2133
|
markCurrent(target.file)
|
|
2011
2134
|
// README 首屏在正文前插一排阅读路径;切到别的文档时随正文一起换掉
|
|
2012
2135
|
if (target.file === DOCS[0].file) {
|
|
@@ -449,6 +449,16 @@ demo 侧(第 ② 条):`docs/demos/gisStyle.js` 的 `buildGisLineRules(laye
|
|
|
449
449
|
|
|
450
450
|
**验证**:`npx tsc --noEmit` 0 错、`npm run build` 通过、`node docs/steps/check-doc-coverage.mjs` 全部命中;十二页自测逐页跑完(`selftest-perf` 85 → **88** 条全绿,新增的 3 条量的是「8000 条线放大之后批次只剩 27 条 / 相机挪回来又回到 8000 / 来回一趟整幅像素一模一样(差异 0 / 241164)」,另加 1 条 DIAG;`selftest-features` 295 → **299** 条,新增的 4 条按画布正中两条粗线交叉处的像素判红蓝:默认蓝(后写的在上)→ 规则写 `zIndex: 5` 变红 → `updateLine` 给另一条写 `zIndex: 9` 又变蓝 → 写回 0 回到红;其余各页条数与改前一致,`selftest-features` 2 条 noMsaa、`selftest-demos` 1 条 LabelDemo 是既有失败,与本轮无关)。
|
|
451
451
|
|
|
452
|
+
### 15.48 通道解析 / 快照路径拆分与直接连接查询(本轮)
|
|
453
|
+
|
|
454
|
+
**需求**(修改.txt):①「刚刚修改为什么没有更新文档」——补齐上一轮通道性能优化与 `removeChannel` 修复的实现记录;②新增一个按节点集合获取直接通道或线路的方法,传一组节点 id,没有结果返回空,两端必须节点之间存在。
|
|
455
|
+
|
|
456
|
+
**上一轮实现补记**:`resolveChannels()` 逐组只解析一次成员,后续车道与骨架共用;简略组只给代表槽生成居中几何,渲染、补丁、命中与边界测量都跳过空槽,状态里的 `offsets` / `spacing` 仍是整组车道。`channelPathsFor()` 与 `channelSnapshotPathAt()` 把「实际要画的路径」和「对外快照的完整路径」拆开:前者不碰隐藏成员,后者按成员原车道惰性补全,所以 `getChannels()` / `getChannelGroupWaypoints()` 不会因简略而出现空路径或错车道。`channelGroupsOf(channel, false)` 让只读路径直接复用声明,`lineChannelIndexIn()` 把复制载荷的反复分组扫描收成一次索引,`removeLines()` 用预建索引与 Set 去重;`removeChannel()` 改按 `channelLineIdsOf()` 取成员,只写 `groups` 的通道也会把组内回线全部删净。20 000 回线 / 4 分组实测:完整构建 **1198.7 → 134.0 ms**、简略构建 **922.0 → 26.6 ms**、复制 **3899 → 682.8 ms**、删除 **2895 → 685.8 ms**。
|
|
457
|
+
|
|
458
|
+
**直接连接查询**:`create.js` 新增 `getDirectConnections(pointIds)`。输入先按真实 `points` id 解析、字符串归一后去重,少于两个有效节点直接返回 `[]`;随后扫一遍通道、一遍线路,只保留两端都在集合里且端点不同的边。通道走 `channelEndsOf()`,即声明优先;只写 `groups` 的通道从第一条成员回线继承端点。线路只认自己的 `from` / `to`,所以纯 `path` 线路、自环、端点不在 `points` 或不在输入集合里的边都跳过,不存在多跳推导。结果先按 `channels` 数据顺序、再按 `lines` 数据顺序,通道和它的成员回线可以同时出现;每项带 `type`、`from` / `to`(id / 下标 / 数据对象)与 `item`,通道另有 `channelId` / `channelIndex` / `lineIds`,线路另有 `lineId` / `lineIndex`。空结果严格为 `[]`,查询不依赖当前选中、筛选或显隐,也不改数据。
|
|
459
|
+
|
|
460
|
+
**类型、文档与验证**:`types.d.ts` 补 `GisViewDirectConnectionNode` / `GisViewDirectChannelConnection` / `GisViewDirectLineConnection` / `GisViewDirectConnection` 与实例签名;manual 09 新增查询口径,16 / 17 / 18 补主表、参数和示例;`selftest-features` 新增四条,覆盖集合内外的边、反向端点、groups-only 通道继承端点、自环 / 未绑定线路与空表。公开成员由 **272** 增至 **273**(**267 → 268** 个方法,属性仍 5 个)。详细验证见本轮 aimd 记录。
|
|
461
|
+
|
|
452
462
|
---
|
|
453
463
|
|
|
454
464
|
[← 15-03 逐轮记录:性能与修复(下)](15-03-%E9%80%90%E8%BD%AE%E8%AE%B0%E5%BD%95-%E6%80%A7%E8%83%BD%E4%B8%8E%E4%BF%AE%E5%A4%8D-%E4%B8%8B.md) · [实现原理目录](../GisView实现原理.md) · [16-01 优化与取舍(上) →](16-01-%E4%BC%98%E5%8C%96%E4%B8%8E%E5%8F%96%E8%88%8D-%E4%B8%8A.md)
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
## 坐标、相机与像素
|
|
6
6
|
|
|
7
7
|
- **世界坐标**:`x` / `y` 就是数据里的数值(经纬度、平面坐标都行),组件不做投影、不做坐标轴翻转。数据范围由节点与线路顶点共同决定(`getBounds()`)。
|
|
8
|
-
- **相机**:`{ center: [x, y], scale }`,`scale` 的单位是**屏幕 CSS 像素 / 世界单位**(`getCamera()` / `setCamera()`)。`fitView(padding)` 适应整份数据,`zoomToBounds(bounds, padding)` 适应一段范围,`zoomTo(scale, origin)` 直接设比例,`zoomBy(factor, origin)` 按锚点缩放,`focusOn(target
|
|
8
|
+
- **相机**:`{ center: [x, y], scale }`,`scale` 的单位是**屏幕 CSS 像素 / 世界单位**(`getCamera()` / `setCamera()`)。`fitView(padding)` 适应整份数据,`zoomToBounds(bounds, padding)` 适应一段范围,`zoomTo(scale, origin)` 直接设比例,`zoomBy(factor, origin)` 按锚点缩放,`focusOn(target)` 缺省只挪中心。
|
|
9
9
|
- **滚轮缩放**:以光标为锚点,`deltaY` 100 对应 1.12 倍 —— 缩放量按 `deltaY` 的大小算(`deltaMode` 是行 / 页时先折算成像素),触摸板的连续小位移因此是平滑的小步长,鼠标滚轮的一格仍是原来那一步,一次甩得再大也有上限(`deltaY` 夹在 ±240,免得某个设备一次甩出十倍)。**缩放缺省是关的**(`interactive` / `zoom` 都没写时滚轮完全不接),写 `interactive: true` 或 `features: { zoom: true }` / `features: 'view'` 才接;接着的时候一律 `preventDefault()`(含 Ctrl + 滚轮的浏览器缩放)。
|
|
10
10
|
- **三档坐标口径**(`world` 不多余:数据 `x` / `y` 就是世界坐标,事件载荷里叫 `world` 只是标口径;三档之间是「客户端坐标 ↔ 画布 CSS 像素 ↔ 世界坐标」的换算链):
|
|
11
11
|
- **世界坐标(`x` / `y`)**:数据、相机、几何读数、`focusOn` 与拖拽落点用的都是这一套,没有第二套;
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
| `channelTangentInset` | `number \| null` | `null` | 两端切点往节点里收多少 CSS 像素:缺省(`null`)按成员回线里最粗那条的线宽收,线因此不会从节点边缘探出去;`0` 表示切点正好落在节点边上,**负数外收**(切点往节点外让、回线整段比节点宽);单个通道可用 `tangentInset` 覆盖;内收两侧合计最多收掉节点宽度的 40%,外收单侧最多让出 50% |
|
|
27
27
|
| `channelMaxGroups` | `number` | `0` | 一条通道最多几个分组(`0` 表示不限):新增通道时用来判断还能不能变成新分组,见「新增通道」 |
|
|
28
28
|
| `channelGroupMaxLines` | `number` | `0` | 一个分组最多几条回线(`0` 表示不限):新增通道时用来判断还能不能并进某一组,见「新增通道」 |
|
|
29
|
+
| `channelSimplify` | `boolean \| GisViewChannelSimplifyOptions` | `false` | 通道简略:`true` 用缺省阈值 `4`;对象可调 `enabled` / `threshold` / `style`。分组回线数严格大于阈值时只画一条代表线,见「通道简略(channelSimplify)」 |
|
|
29
30
|
| `channelDraftStyle` | `GisViewChannelDraftStyle` | 蓝色 2px + 两端圆点,箭头关闭 | 新增通道草稿预览的全局样式:`color` / `width` / `dot` / `dotColor` / `dots`(`false` 关示例点,或 `{ show, size, color, shape, from, to }` 分端配置;示例点固定在点中的节点中心)/ `layer`(`'above'` 默认,`'below-points'` 让示例线 / 箭头 / `customDraw` 位于真实节点之下)/ `arrow` / `arrowSize` / `arrowPositions` / `arrowReverse` / `arrowColor` / `circuitSpacing` / `opacity` / `customDraw`;`beginAddChannel({ channelDraftStyle })` 可按这一次草稿覆盖,`updateAddChannelStyle(patch)` 可在草稿期间增量修改 |
|
|
30
31
|
| `webglLayers` | `GisViewWebGLLayer[]` | `[]` | WebGL 自定义绘制层:每层提供 `draw({ gl, canvas, viewport, camera, frame, project, unproject, requestRender })`,在内置内容之后按 `order` 绘制;运行时也可用 `addWebGLLayer` / `updateWebGLLayer` / `removeWebGLLayer` 维护 |
|
|
31
32
|
| `background` | `GisViewBackground` | 浅色底 | 背景层,支持底色、图片与 GeoJSON |
|
|
@@ -36,10 +37,10 @@
|
|
|
36
37
|
| `effects` | `GisViewEffectsInput` | 关 | 动画效果(全局缺省):线路上的跑动图标(`line`,ECharts `lines.effect` 那一类)与节点上的扩散涟漪(`point`,`effectScatter` 那一类),逐要素用 `points[].effect` / `lines[].effect` 覆盖;没配就是关的,但「只在数据里逐条配了 `effect`」的场景照样会动。`false` 或 `{ enabled: false }` 是**一处关掉**(谁都别动);运行时有 `updateOptions({ effects })` / `getEffects()` / `getLineEffects()`,见「动画效果(effects)」 |
|
|
37
38
|
| `lineDirection` | `GisViewLineDirectionInput` | 关(`null`) | 线路方向箭头(全局缺省):沿线摆一串静态箭头,朝向跟着线路切向走(起点 / `from` 那一端 → 终点,`reverse` 指回上游),按弧长等分、缺省每条线只在中点一个;逐条线路用 `lines[].direction` 覆盖,写法与 `effects` 同构(`true` 用全局、对象逐字段覆盖、`false` / `null` 关掉),见「线路方向箭头(lineDirection)」 |
|
|
38
39
|
| `prebake` | `GisViewPrebakeOptions \| true` | 关 | 贴图符号预热:把「这次画面会出现什么」提前告诉组件 —— 两种写法:`combos` 逐组合(精确,`getSymbolCombos()` 收出来的那份)/ `symbols × pointColors × sizes` 与 `lineColors × 线路动画图标` 全排列(省事,颜色与尺寸由同一个字段决定时会多烤很多)—— 第一帧之前就烤好,画到它们时命中的是现成的贴图(省掉解码 + 光栅化那一下);组合数与数据量无关,不配就是从前那条按需路径。读数 `getPrebake()` / `getSymbolCombos()`、手动再烤一遍 `runPrebake()`,见「贴图符号预热(prebake)」 |
|
|
39
|
-
| `label` | `GisViewLabelOptions \| GisViewLabelOptions[]` | 无 | 节点标签:内容 / 位置 / 显隐 / 避让 / 拖动与编辑都可配,**写数组就是同一个节点上多条标签**,与 `lineLabel`
|
|
40
|
+
| `label` | `GisViewLabelOptions \| GisViewLabelOptions[]` | 无 | 节点标签:内容 / 位置 / 显隐 / 避让 / 层级 / 缩放字号 / 拖动与编辑都可配,**写数组就是同一个节点上多条标签**,与 `lineLabel` 共用一套避让网格;`zIndex` 显式定层,`followNodeZIndex` 跟随节点样式链,`zoomScale` 控制字号是否随地图缩放,见「节点标签」 |
|
|
40
41
|
| `labelOptimize` | `boolean` | `false` | 标签显示优化开关:**缺省关 = 强制显示**(不避让、不按 `maxCount` 截断、不设 `scanLimit` / 扫描预算,节点 / 线路的每个可见要素该出现的标签一条不少);写 `true` 与从前一致 —— 避让 / 换落点 / 数量上限 / 候选上限全部生效。标签订得密、数据量大(十万级)时建议打开,见「标签显示优化开关」 |
|
|
41
42
|
| `labelRender` | `'auto' \| 'canvas' \| 'dom'` | `'auto'` | 纯文本标签的容器渲染方式:`auto` 在强制显示档(`labelOptimize` 未开且未进密集档)下,同一层纯文本标签达到 1024 条时改画到一张 Canvas;`canvas` 不受数量阈值限制,优化档 / 密集档也强制画布并直接用画布尺寸参与避让;`dom` 始终逐条建 `.gis-view__label`。HTML / 元素内容 / 可拖拽 / 可编辑 / 超出 Canvas 样式能力的标签仍走 DOM。只影响容器,不改内容、锚点、显隐以及 `maxCount` / `when` / `scanLimit` 等优化策略,见「标签容器渲染(labelRender)」 |
|
|
42
|
-
| `lineLabel` | `GisViewLineLabelOptions \| GisViewLineLabelOptions[]` | 无 | 线路标签:位置沿线走(比例 / 百分比 /
|
|
43
|
+
| `lineLabel` | `GisViewLineLabelOptions \| GisViewLineLabelOptions[]` | 无 | 线路标签:位置沿线走(比例 / 百分比 / 绝对距离),内容、避让、显隐、层级与缩放字号都可配,与节点标签共用一套避让网格;**写数组就是同一条线上多条标签**,见「线路标签」 |
|
|
43
44
|
| `labelStates` | `GisViewLabelState[]` | 无 | 标签的运行时状态(`getLabelStates()` 的那一份:拖出来的偏移、改过的内容与样式、运行时加的标签、隐藏覆盖):创建时喂回来就回显,等价于创建之后调 `setLabelStates(states)`;`updateOptions({ labelStates })` 同样认。`exportData({ format: 'input' })` 的结果里就叫 `labelStates`,存档 → 回灌直接接上 |
|
|
44
45
|
| `graphics` | `GisViewGraphic[]` | 无 | 与节点无关的扩展图形:按世界坐标放 SVG 路径 / 图片 / Canvas,支持锚点、偏移、旋转、透明度、`zIndex` 与 `scaleWithView`;位于画布之上、标签之下,运行时用 `addGraphic` / `addGraphics` / `updateGraphic` / `removeGraphic` / `clearGraphics` 增删改,见「扩展图形(graphic)」 |
|
|
45
46
|
| `tooltip` | `GisViewTooltipOptions` | 无 | 悬停提示:点 / 线 / 通道分别配置内容,见「悬浮提示」 |
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
| `boxSelect` | `boolean` | `false` | 是否允许按住框选快捷键(`shortcuts.boxSelect`,默认 Shift)拖动鼠标框选要素;**缺省关**,写 `boxSelect: true` 或 `features: { boxSelect: true }` 才开。框选默认只收节点,`selectionKinds` 可把线路 / 通道也纳入 |
|
|
59
60
|
| `multiSelect` | `boolean` | `false` | 多选开关:打开后不用按修饰键,直接单击节点 / 线路就取反累加选中(与按住 `shortcuts.multiSelect` 点击同一套行为、同一个 `multiSelectStyle`;取反那一下不经过 `onClick`,`onSelectChange.action.type` 是 `toggleSelect`);**缺省关**,关着时多选走框选(`boxSelect`)与按住多选快捷键(默认 Ctrl / ⌘)。运行时 `updateOptions({ multiSelect })` 切换只重画一帧、不重排场景 |
|
|
60
61
|
| `selectTrigger` | `'click' \| 'dblClick'` | `'click'` | 选中触发方式:`click` 第一次单击就改选中集;`dblClick` 第一下只派发 `onClick`,等双击判定命中的第二下才改选中集,并同时派发 `onClick` 与 `onDblClick`。Ctrl / ⌘ 多选与 `multiSelect` 在双击模式下同样等第二下才取反。运行时走 `updateOptions({ selectTrigger })`,只重画一帧、不重排场景 |
|
|
61
|
-
| `selectionKinds` | `GisViewSelectionKindsInput` | 无(框选只收节点;Ctrl 多选收节点 / 线路 / 通道) | 框选与 Ctrl / 多选点击的类型过滤:`'point'` 节点、`'line'` 通道外的独立线路、`'channel'`
|
|
62
|
+
| `selectionKinds` | `GisViewSelectionKindsInput` | 无(框选只收节点;Ctrl 多选收节点 / 线路 / 通道) | 框选与 Ctrl / 多选点击的类型过滤:`'point'` 节点、`'line'` 通道外的独立线路、`'channel'` 通道回线;另有 `'lineEndpoints'` / `'channelEndpoints'`,只在框选时要求线路 / 通道两端节点都在框内。可写数组任意组合,`'all'` / `true` 全开,`false` / `null` 全关。通道回线只归 `channel` 管,通道外的线路只归 `line` 管;通道回线仍按 `channelSelectMode` 摊开。不写时保留旧口径;普通单选与 `select` / `selectFeatures` 不受它限制。运行时走 `updateOptions({ selectionKinds })`,见「框选」与「选择类型过滤」 |
|
|
62
63
|
| `selectionBoxStyle` | `GisViewSelectionBoxStyle` | 蓝底 0.16 透明 + 1px 蓝框 | 框选矩形的填充与边框:`fill`、`fillOpacity`、`stroke`、`strokeWidth` |
|
|
63
64
|
| `selectionOnTop` | `boolean` | `true` | 选中的节点 / 拖动中的整组 / 待确认合并的目标节点,以及选中线路所在的整条通道,是否画在所有要素之上(与 `zIndex` 无关),见「选中 / 拖动的层级」 |
|
|
64
65
|
| `channelSelectMode` | `'line' \| 'group' \| 'channel'` | `'line'` | 通道选中模式:点中通道里的一条回线时选中什么 —— `'line'` 只选这一条、`'group'` 连它所在的分组一起、`'channel'` 整条通道(所有分组的回线);通道以外的线路永远只选自己。普通点选与 Ctrl / ⌘ + 点击加点共用这一档高亮范围;Ctrl / ⌘ + 点击在 `group` / `channel` 下按整批取反;切换走 `updateOptions({ channelSelectMode })`,只重画一帧、不重排场景,见「通道选中模式」 |
|
|
@@ -79,13 +80,16 @@
|
|
|
79
80
|
| `shortcuts` | `GisViewShortcuts` | 见「快捷键」 | 所有快捷键都可自定义:框选 / 多选 / 加点 / 复制 / 粘贴 / 取消 / 删除 / 适应视图,没写的动作沿用默认值,写 `false` 等于关掉这个动作的快捷键 |
|
|
80
81
|
| `copy` | `GisViewCopyOptions` | 缺省关 | 复制节点(**写了这份配置才算开**,`enabled: false` 显式关掉):`enabled` 开关、`offset` 落点偏移(默认 `[28, 24]` 像素)、`autoCommit`(交互入口落地前是否自动确认:不写就是落地,`false` 停在预览态等 `commitPointCopy()` / 载荷里的 `payload.commit()`)、`idPrefix`(默认 `copy-`)、`createId` / `createItem` 定制复制品,见「节点复制」 |
|
|
81
82
|
| `remove` | `GisViewRemoveOptions` | 缺省关 | 删除选中的拐点 / 线路 / 节点(**写了这份配置才算开**,`enabled: false` 显式关掉):`enabled` 开关、`scope`(`confirm()` 不带参数时的缺省范围:`'lines'` 只删选中的回线 / `'groups'` 连所在分组 / `'channels'` 连整条通道,缺省 `'lines'`)、`confirm`(不写停在 `pending` 等使用方裁决 / `false` 直接删 / 函数自行裁决,支持 Promise)。Delete 键与 `requestRemove()` 都先出一份「要删什么、连带什么」的载荷,确认之后才动数据;删节点会连挂在它身上的线路与被它锚定的通道一起删,见「删除(remove)」 |
|
|
82
|
-
| `merge` | `GisViewMergeOptions` | 缺省关 | 合并节点(**写了这份配置才算开**,`enabled: false` 显式关掉):`enabled` 开关、`trigger` 触发时机(`'collision'` 两个节点半径相碰 / `'center'` 拖动节点中心进入目标节点区域)、`distance` 额外像素容差、`confirm`(不写停在 `pending` 等使用方裁决 / `false` 直接合并 / 函数自行裁决)、`channelGroups`(`'keep'` 各自保留分组 / `'merge'` 合成一个分组)、`createItem` 定制合并结果,见「节点合并」 |
|
|
83
|
+
| `merge` | `GisViewMergeOptions` | 缺省关 | 合并节点(**写了这份配置才算开**,`enabled: false` 显式关掉):`enabled` 开关、`trigger` 触发时机(`'collision'` 两个节点半径相碰 / `'center'` 拖动节点中心进入目标节点区域)、`distance` 额外像素容差、`confirm`(不写停在 `pending` 等使用方裁决 / `false` 直接合并 / 函数自行裁决)、`channelGroups`(`'keep'` 各自保留分组 / `'merge'` 合成一个分组)、`maxKeys` 选哪些字段取双方最高、`createItem` 定制合并结果,见「节点合并」 |
|
|
83
84
|
| `minScale` / `maxScale` | `number` | `0.002` / `20000` | 缩放范围(像素 / 世界单位) |
|
|
84
85
|
| `fitPadding` | `number` | `48` | 适应视图时四周留白(CSS 像素);留白比画布还大时按「内容至少留 48px」反过来压留白,不会把内容挤成一个点 |
|
|
85
86
|
| `fitOnInit` | `boolean` | `true` | 首次拿到数据时自动适应视图;配了 `initialView` 时以它为准(`false` 只关掉「适应」,`initialView` 仍然生效,见「初始视图」) |
|
|
87
|
+
| `center` | `GisViewCoordinate` | 无 | 首屏中心 `[x, y]` / `{ x, y }`,是 `initialView.center` 的顶层简写;显式给出非空 `initialView` 时以那一份为准 |
|
|
88
|
+
| `scale` | `number` | 无 | 首屏绝对比例(像素 / 世界单位),是 `initialView.scale` 的顶层简写;显式给出非空 `initialView` 时以那一份为准 |
|
|
86
89
|
| `initialView` | `GisViewInitialView` | 无 | 首次加载的相机落位:中心点、绝对比例、相对放大倍数或要适应的范围,见「初始视图」 |
|
|
87
90
|
| `progressiveInit` | `boolean` | `true` | 大数据(2 万点以上)初始化是否从视图中心向外发散渲染:首帧只排中心附近的一批,剩下的分帧往外补,见「大数据量」 |
|
|
88
91
|
| `statsInterval` | `number` | `250` | `onStats` 的最小间隔(毫秒),`0` 表示每帧都发 |
|
|
92
|
+
| `idleTimeout` | `number` | `0`(关闭) | 用户操作空闲阈值(毫秒):根节点上这么久没有指针 / 滚轮 / 键盘活动就发一次 `onIdle` / `idle`;每个空闲段只触发一次,恢复操作后重新计时 |
|
|
89
93
|
| `renderEmitInterval` | `number` | `400` | `onRender` 的节流间隔(毫秒),`0` 与 `onStats` 同拍(再配上 `statsInterval: 0` 就是每帧一条) |
|
|
90
94
|
| `plugins` | `GisViewPlugin[]` | `[]` | 插件:`(view, context) => hook`,返回的 `destroy` 在实例销毁时倒序回调,见「插件」 |
|
|
91
95
|
| `zoomStep` | `number` | `1.4` | `zoomIn()` / `zoomOut()` 的步进倍率 |
|
|
@@ -108,13 +112,13 @@
|
|
|
108
112
|
| --- | --- |
|
|
109
113
|
| 总开关与历史 | `features` · `history` |
|
|
110
114
|
| 数据与背景 | `points` · `lines` · `channels` · `pointCluster` · `background` |
|
|
111
|
-
| 通道几何 | `channelWidth` · `channelInset` · `channelNodeWidth` · `channelTangentInset` · `channelMaxGroups` · `channelGroupMaxLines` · `channelDraftStyle` · `channelSelectMode` · `channelWaypointDragMode` |
|
|
115
|
+
| 通道几何 | `channelWidth` · `channelInset` · `channelNodeWidth` · `channelTangentInset` · `channelMaxGroups` · `channelGroupMaxLines` · `channelSimplify` · `channelDraftStyle` · `channelSelectMode` · `channelWaypointDragMode` |
|
|
112
116
|
| 样式与规则 | `pointStyle` · `lineStyle` · `pointRules` / `lineRules` · `heatmap` · `effects` · `lineDirection` · `prebake` · `label` · `labelOptimize` · `labelRender` · `lineLabel` · `labelStates` · `tooltip` · `pointSizeScale` / `lineWidthScale`、`pointZoomScale` / `lineZoomScale`、`zoomBaseScale` · `cursorStyle` · `gridColor` · `gridSize` · `showGrid` |
|
|
113
117
|
| 状态样式与选中 | `pointHoverStyle` / `pointSelectStyle` · `lineHoverStyle` / `lineSelectStyle` · `pointMultiSelectStyle` / `pointBoxSelectStyle` · `lineMultiSelectStyle` · `defaultHighlight` · `selectionBoxStyle` · `selectionOnTop` · `waypointStyle` / `waypointSelectStyle` |
|
|
114
118
|
| 交互开关 | `boxSelect` · `multiSelect` · `selectTrigger` · `waypointEditable` · `waypointVisibility` · `interactive` · `preventContextMenu` · `clickable` · `draggable` · `liveDrag` · `lineFollowsNode` · `shortcuts` · `copy` · `remove` · `merge` |
|
|
115
|
-
| 视图与相机 | `minScale` / `maxScale` · `fitPadding` · `fitOnInit` · `initialView` · `zoomStep` |
|
|
119
|
+
| 视图与相机 | `minScale` / `maxScale` · `fitPadding` · `fitOnInit` · `center` / `scale` · `initialView` · `zoomStep` |
|
|
116
120
|
| 画质与渲染 | `quality` · `width` / `height` · `pixelRatio` · `maxCanvasPixels` · `antialias` · `interactionThinLines` · `interactionNoMsaa` · `renderer` · `webglLayers` |
|
|
117
|
-
| 大数据(筛选 / 搜索 / 读数) | `denseMode` · `filter` · `filterWorker` · `searchWorker` · `progressiveInit` · `statsInterval` · `renderEmitInterval` |
|
|
121
|
+
| 大数据(筛选 / 搜索 / 读数) | `denseMode` · `filter` · `filterWorker` · `searchWorker` · `progressiveInit` · `statsInterval` · `idleTimeout` · `renderEmitInterval` |
|
|
118
122
|
| 外部界面与集成 | `minimap` · `plugins` · `ariaLabel` |
|
|
119
123
|
|
|
120
124
|
### 总开关与历史
|
|
@@ -276,6 +280,25 @@ view.updateOptions({ channelWidth: 0.08 }) // 没绑节点的那几条跟着
|
|
|
276
280
|
- **默认值**:`0`
|
|
277
281
|
- **说明**:一个分组最多几条回线(`0` 表示不限):新增通道时用来判断还能不能并进某一组,见「新增通道」
|
|
278
282
|
|
|
283
|
+
#### `channelSimplify`
|
|
284
|
+
|
|
285
|
+
- **类型**:`boolean | GisViewChannelSimplifyOptions`
|
|
286
|
+
- **默认值**:`false`
|
|
287
|
+
- **说明**:通道简略。`true` 使用缺省阈值 `4`;对象写法 `{ enabled, threshold, style }` 本身即开启,只有 `enabled: false` 才关闭。分组回线数**严格大于** `threshold`(向下取整,最小 `1`)时只画该组第一条 `visible !== false` 的回线,其余回线暂不绘制 / 不参与拾取,`getLineStyle()` 对折叠成员返回 `null`。代表线压在分组骨架中线,`style` 按 `GisViewLineStyle` 覆盖颜色、线宽、线型等展示字段。没有 `groups` 的通道按一整组处理;`getData()`、`getChannelGroups()` 与导出始终保留全部回线,关闭后原样恢复。运行时 `updateOptions({ channelSimplify })` 会重解析通道,见「通道简略(channelSimplify)」
|
|
288
|
+
- **参考**:见「通道简略(channelSimplify)」一节,子字段在主表里展开
|
|
289
|
+
- **示例**:
|
|
290
|
+
|
|
291
|
+
```js
|
|
292
|
+
createGisView(container, {
|
|
293
|
+
channelSimplify: {
|
|
294
|
+
enabled: true,
|
|
295
|
+
threshold: 4,
|
|
296
|
+
style: { color: '#ff6b35', width: 3, dash: [8, 4] }
|
|
297
|
+
}
|
|
298
|
+
})
|
|
299
|
+
view.updateOptions({ channelSimplify: false }) // 关闭后全部回线恢复
|
|
300
|
+
```
|
|
301
|
+
|
|
279
302
|
#### `channelDraftStyle`
|
|
280
303
|
|
|
281
304
|
- **类型**:`GisViewChannelDraftStyle`
|
|
@@ -398,7 +421,7 @@ view.updateOptions({ prebake: { combos: view.getSymbolCombos().combos } })
|
|
|
398
421
|
|
|
399
422
|
- **类型**:`GisViewLabelOptions | GisViewLabelOptions[]`
|
|
400
423
|
- **默认值**:无
|
|
401
|
-
- **说明**:节点标签:内容 / 位置 / 显隐 / 避让 / 拖动与编辑都可配,**写数组就是同一个节点上多条标签**,与 `lineLabel`
|
|
424
|
+
- **说明**:节点标签:内容 / 位置 / 显隐 / 避让 / 层级 / 缩放字号 / 拖动与编辑都可配,**写数组就是同一个节点上多条标签**,与 `lineLabel` 共用一套避让网格。`zIndex` 显式指定标签层级;`followNodeZIndex: true` 时取节点样式链(节点自身 > 规则 > `pointStyle`)的 `zIndex`,并让更高层节点图标压住这条标签;`zoomScale` 是字号随地图缩放的指数(`0` 固定屏幕字号、`1` 与地图同倍率),见「节点标签」
|
|
402
425
|
- **参考**:见「节点标签」一节,子字段在那里的表里逐个展开
|
|
403
426
|
|
|
404
427
|
#### `labelOptimize`
|
|
@@ -419,7 +442,7 @@ view.updateOptions({ prebake: { combos: view.getSymbolCombos().combos } })
|
|
|
419
442
|
|
|
420
443
|
- **类型**:`GisViewLineLabelOptions | GisViewLineLabelOptions[]`
|
|
421
444
|
- **默认值**:无
|
|
422
|
-
- **说明**:线路标签:位置沿线走(比例 / 百分比 /
|
|
445
|
+
- **说明**:线路标签:位置沿线走(比例 / 百分比 / 绝对距离),内容、避让、显隐、层级与缩放字号都可配,与节点标签共用一套避让网格;**写数组就是同一条线上多条标签**。`zIndex` 决定线路标签之间的先后,`zoomScale` 控制字号是否随地图缩放,见「线路标签」
|
|
423
446
|
- **参考**:见「线路标签」一节,子字段在那里的表里逐个展开
|
|
424
447
|
|
|
425
448
|
#### `labelStates`
|
|
@@ -592,7 +615,7 @@ createGisView(container, {
|
|
|
592
615
|
|
|
593
616
|
- **类型**:`boolean`
|
|
594
617
|
- **默认值**:`true`
|
|
595
|
-
- **说明**:选中的节点 / 拖动中的整组 /
|
|
618
|
+
- **说明**:选中的节点 / 拖动中的整组 / 待确认合并的目标节点,以及选中线路所在的整条通道,是否抬层绘制(与 `zIndex` 无关)。选中的线路 / 通道压在普通节点之上,但两端节点会再抬一层压回线路之上,保证端点与线路接头可见;见「选中 / 拖动的层级」
|
|
596
619
|
- **参考**:见「选中 / 拖动的层级(selectionOnTop)」一节,子字段在那里的表里逐个展开
|
|
597
620
|
|
|
598
621
|
#### 拐点样式(`waypointStyle` / `waypointSelectStyle`)
|
|
@@ -652,7 +675,7 @@ view.updateOptions({ selectTrigger: 'click' })
|
|
|
652
675
|
|
|
653
676
|
- **类型**:`GisViewSelectionKindsInput`
|
|
654
677
|
- **默认值**:无(框选只收节点;Ctrl 多选仍收节点 / 线路 / 通道)
|
|
655
|
-
- **说明**:限定框选与 Ctrl(⌘)/ `multiSelect` 点击能选中哪几类要素。`'point'` 是节点、`'line'` 是通道外的独立线路、`'channel'`
|
|
678
|
+
- **说明**:限定框选与 Ctrl(⌘)/ `multiSelect` 点击能选中哪几类要素。`'point'` 是节点、`'line'` 是通道外的独立线路、`'channel'` 是通道回线;`'lineEndpoints'` / `'channelEndpoints'` 是框选专用的另一种口径,要求线路 / 通道自己的两端节点都落在框内,纯 `path`、缺失端点与自环跳过。数组可任意组合,`'all'` / `true` 五档全开,`false` / `null` 全关;新旧线路 / 通道口径并存时取并集。通道回线只受 `channel` 管、通道外的线路只受 `line` 管;选中通道回线时仍按 `channelSelectMode` 决定只选这一条 / 一组 / 整条通道。端点口径不会顺带选中两端节点,也不依赖 `point` 是否开启。**不写时保持旧口径**:框选只收节点,Ctrl / 多选点击收节点与线路;显式写 `selectionKinds` 后框选按完整过滤、Ctrl / 多选点击只认互斥的 `point` / `line` / `channel`。普通单击与 `select` / `selectFeatures` 接口不受限制;`selectInBox(box, { selectionKinds })` 可一次性覆盖。
|
|
656
679
|
- **参考**:见「08 选中与拐点」的「框选」与「选择类型过滤(selectionKinds)」
|
|
657
680
|
- **示例**:
|
|
658
681
|
|
|
@@ -663,9 +686,10 @@ createGisView(container, {
|
|
|
663
686
|
channelSelectMode: 'channel' // 真要选通道回线时整条通道一起选
|
|
664
687
|
})
|
|
665
688
|
|
|
666
|
-
view.updateOptions({ selectionKinds: 'all' }) //
|
|
689
|
+
view.updateOptions({ selectionKinds: 'all' }) // 五档全开(节点 / 两类旧口径 / 两类端点口径)
|
|
667
690
|
view.updateOptions({ selectionKinds: false }) // 框选 / Ctrl 多选都不改选中集
|
|
668
691
|
view.selectInBox(rect, { selectionKinds: 'channel' }) // 仅这一次只框通道
|
|
692
|
+
view.selectInBox(rect, { selectionKinds: ['lineEndpoints', 'channelEndpoints'] }) // 只框两端都在框里的线路 / 通道
|
|
669
693
|
```
|
|
670
694
|
|
|
671
695
|
#### `waypointEditable`
|
|
@@ -790,14 +814,15 @@ view.resolveRemove('all') // 或 'points' / false
|
|
|
790
814
|
| `distance` | `number` | `0` | 额外触发容差(CSS 像素):`collision` 加在两个节点半径之和上,`center` 加在目标节点半径上,负数按 0 处理 |
|
|
791
815
|
| `confirm` | `false \| (payload) => boolean \| void \| Promise<boolean \| void>` | 不写(停在 `pending`) | 确认方式:不写时组件不弹任何界面,等使用方调 `payload.confirm()` / `resolvePointMerge()`;`false` 松手直接合并;函数自行裁决,返回 / resolve `false` 取消,返回 `undefined` 表示继续等使用方接管 |
|
|
792
816
|
| `channelGroups` | `'keep' \| 'merge'` | `'keep'` | 两个节点合并后、两端撞成同一条通道时回线怎么分组:`keep` 各自保留原分组,`merge` 合成一个分组(回线取并集) |
|
|
793
|
-
| `
|
|
817
|
+
| `maxKeys` | `string[] \| string` | `[]` | 合并后取双方最高值的字段:数组或逗号分隔字符串(去空白、去重),例如 `['vn_kv', 'value']` / `'vn_kv,value'`。只对双方能解析成有限数字的值取 `Math.max`,只有一方有效就用那一方,两边都无效时保持保留节点的原值;其它业务字段全部取保留节点。配了 `createItem` 时不参与 |
|
|
818
|
+
| `createItem` | `(source, target, context) => GisViewPoint` | 内置合并规则 | 整份接管合并后的业务字段。`context` 含双方数据 / 坐标 / 样式快照 / `lines` / `channels` / `view`;不写时以保留节点为底(名称、图标类型等字段取保留端),只有 `maxKeys` 列出的字段取双方最高值(缺省不取),尺寸取双方最大、图标类型用保留端。坐标、id 与 `mergeInfo` 始终由组件维护 |
|
|
794
819
|
|
|
795
820
|
`merge` **没有 `offset` 字段**:拖拽合并的落点由拖动位置决定,合并后保留端的坐标不会被额外平移;复制品的屏幕偏移属于另一份配置 `copy.offset`(默认 `[28, 24]` 像素),两者不要混写。
|
|
796
821
|
- **参考**:见「节点合并」一节,子字段在那里的表里逐个展开
|
|
797
822
|
- **示例**:
|
|
798
823
|
|
|
799
824
|
```js
|
|
800
|
-
createGisView(container, { merge: { enabled: true, trigger: 'center', distance: 6, confirm: false } })
|
|
825
|
+
createGisView(container, { merge: { enabled: true, trigger: 'center', distance: 6, confirm: false, maxKeys: ['vn_kv', 'value'] } })
|
|
801
826
|
view.mergePoints('a', 'b') // 接口合并
|
|
802
827
|
view.getPointMerge() // 待确认时读预览
|
|
803
828
|
view.getLine('l1') // impact.lineIds 里的 id 按它查线路详情
|
|
@@ -824,6 +849,32 @@ view.getChannel('ch-1') // impact.channelIds 里的 id 按它查通
|
|
|
824
849
|
- **默认值**:`true`
|
|
825
850
|
- **说明**:首次拿到数据时自动适应视图;配了 `initialView` 时以它为准(`false` 只关掉「适应」,`initialView` 仍然生效,见「初始视图」)
|
|
826
851
|
|
|
852
|
+
#### `center`
|
|
853
|
+
|
|
854
|
+
- **类型**:`GisViewCoordinate`
|
|
855
|
+
- **默认值**:无
|
|
856
|
+
- **说明**:首屏中心 `[x, y]` / `{ x, y }`,等价于 `initialView.center`。适合只想在创建时传一个中心点、不想再包一层 `initialView` 的写法;显式给出非空 `initialView` 时整份以 `initialView` 为准,这里的值不参与合并。运行中 `updateOptions({ center })` 会合并到 `initialView`,但和 `initialView` 一样只影响下一次 `applyInitialView()` / 首次落位,不会立刻搬相机;只想马上移动中心用 `setCenter()` / `setCamera({ center })`
|
|
857
|
+
- **参考**:见「初始视图」一节
|
|
858
|
+
- **示例**:
|
|
859
|
+
|
|
860
|
+
```js
|
|
861
|
+
createGisView(container, { points, center: [500, 300], scale: 2 })
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
#### `scale`
|
|
865
|
+
|
|
866
|
+
- **类型**:`number`
|
|
867
|
+
- **默认值**:无
|
|
868
|
+
- **说明**:首屏绝对比例(像素 / 世界单位),等价于 `initialView.scale`,仍然夹在 `minScale` ~ `maxScale` 之间。显式给出非空 `initialView` 时以它为准;运行中 `updateOptions({ scale })` 只改下一次落位,想立刻改当前比例用 `setScale()` / `zoomTo()`。当前读数用 `getScale()` 或 `getCamera().scale`
|
|
869
|
+
- **参考**:见「初始视图」与「缩放范围」两节
|
|
870
|
+
- **示例**:
|
|
871
|
+
|
|
872
|
+
```js
|
|
873
|
+
const view = createGisView(container, { points, center: [500, 300], scale: 2 })
|
|
874
|
+
view.setScale(3) // 运行中立即改比例(锚点缺省视口中心)
|
|
875
|
+
console.log(view.getScale()) // 3
|
|
876
|
+
```
|
|
877
|
+
|
|
827
878
|
#### `initialView`
|
|
828
879
|
|
|
829
880
|
- **类型**:`GisViewInitialView`
|
|
@@ -992,6 +1043,23 @@ view.setFilter(null) // 清掉筛选
|
|
|
992
1043
|
- **默认值**:`250`
|
|
993
1044
|
- **说明**:`onStats` 的最小间隔(毫秒),`0` 表示每帧都发
|
|
994
1045
|
|
|
1046
|
+
#### `idleTimeout`
|
|
1047
|
+
|
|
1048
|
+
- **类型**:`number`
|
|
1049
|
+
- **默认值**:`0`(关闭)
|
|
1050
|
+
- **说明**:用户操作空闲阈值(毫秒)。根节点上超过这么久没有 `pointerdown` / `pointermove` / `pointerup` / `pointercancel` / `wheel` / `keydown`,就回调一次 `onIdle` 并派发 `idle`,载荷是 `{ idleTime, timeout }`。每个空闲段只触发一次,下一次用户操作后重新计时;`getIdleTime()` 随时可读当前空闲时长,不配 `idleTimeout` 也能用。程序化 API 调用不算用户操作、不会重置计时;`updateOptions({ idleTimeout })` 会以这次更新为新的计时起点(写 `0` 关闭)。组件只保留一个定时器,`destroy()` 会清掉它并移除根节点监听
|
|
1051
|
+
- **参考**:见「04 事件与回调」的 `onIdle` / `idle` 与「14 视图与筛选」的「比例读写、画布事件与空闲检测」
|
|
1052
|
+
- **示例**:
|
|
1053
|
+
|
|
1054
|
+
```js
|
|
1055
|
+
const view = createGisView(container, {
|
|
1056
|
+
points,
|
|
1057
|
+
idleTimeout: 60000,
|
|
1058
|
+
onIdle: ({ idleTime }) => console.log(`无操作 ${idleTime}ms`)
|
|
1059
|
+
})
|
|
1060
|
+
console.log(view.getIdleTime())
|
|
1061
|
+
```
|
|
1062
|
+
|
|
995
1063
|
#### `renderEmitInterval`
|
|
996
1064
|
|
|
997
1065
|
- **类型**:`number`
|