raintee-maputils 1.0.52 → 1.0.54
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/dist/index.js +376 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6224,7 +6224,7 @@ const Sttqp = (initVal, taskList, processor) => {
|
|
|
6224
6224
|
const CSnapt = async (fts, lys, style) => {
|
|
6225
6225
|
return new Promise((resolve, reject) => {
|
|
6226
6226
|
createElementById('tem123', async (id) => {
|
|
6227
|
-
const map =
|
|
6227
|
+
const map = mapboxgl.CreateMapboxMap({
|
|
6228
6228
|
container: id,
|
|
6229
6229
|
style: style,
|
|
6230
6230
|
zoom: 12,
|
|
@@ -21429,6 +21429,301 @@ class CustomToggleControl {
|
|
|
21429
21429
|
|
|
21430
21430
|
// RasterLayerController.js
|
|
21431
21431
|
|
|
21432
|
+
// class RasterLayerControl {
|
|
21433
|
+
// constructor() {
|
|
21434
|
+
// this._panel = null;
|
|
21435
|
+
// this._dialog = null;
|
|
21436
|
+
// this._layerListContainer = null;
|
|
21437
|
+
// this._isOpen = false;
|
|
21438
|
+
// this._tempLayers = [];
|
|
21439
|
+
// }
|
|
21440
|
+
|
|
21441
|
+
// onAdd(map) {
|
|
21442
|
+
// this._map = map;
|
|
21443
|
+
|
|
21444
|
+
// this._container = document.createElement('div');
|
|
21445
|
+
// this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group mapboxgl-ctrl-raster-control';
|
|
21446
|
+
|
|
21447
|
+
// this._button = document.createElement('button');
|
|
21448
|
+
// this._button.type = 'button';
|
|
21449
|
+
// this._button.innerHTML = '底图:初始化中';
|
|
21450
|
+
// this._button.style.cssText = `
|
|
21451
|
+
// width: 100%;
|
|
21452
|
+
// padding: 6px 10px;
|
|
21453
|
+
// margin: 0;
|
|
21454
|
+
// font-size: 14px;
|
|
21455
|
+
// font-family: Arial, sans-serif;
|
|
21456
|
+
// background: #f8f9fa;
|
|
21457
|
+
// color: #333;
|
|
21458
|
+
// border: 1px solid #dee2e6;
|
|
21459
|
+
// border-radius: 4px;
|
|
21460
|
+
// cursor: pointer;
|
|
21461
|
+
// text-align: left;
|
|
21462
|
+
// white-space: nowrap;
|
|
21463
|
+
// box-sizing: border-box;
|
|
21464
|
+
// line-height: 1.4;
|
|
21465
|
+
// `;
|
|
21466
|
+
|
|
21467
|
+
// this._button.addEventListener('mouseenter', () => {
|
|
21468
|
+
// this._button.style.background = '#e9ecef';
|
|
21469
|
+
// });
|
|
21470
|
+
// this._button.addEventListener('mouseleave', () => {
|
|
21471
|
+
// this._button.style.background = '#f8f9fa';
|
|
21472
|
+
// });
|
|
21473
|
+
|
|
21474
|
+
// this._button.addEventListener('click', () => {
|
|
21475
|
+
// this._togglePanel();
|
|
21476
|
+
// });
|
|
21477
|
+
|
|
21478
|
+
// this._container.appendChild(this._button);
|
|
21479
|
+
|
|
21480
|
+
// this._map.on('idle', () => this._updateButtonText());
|
|
21481
|
+
// this._map.on('styledata', () => this._updateButtonText());
|
|
21482
|
+
// this._map.on('sourcedata', () => this._updateButtonText());
|
|
21483
|
+
|
|
21484
|
+
// this._updateButtonText();
|
|
21485
|
+
|
|
21486
|
+
// return this._container;
|
|
21487
|
+
// }
|
|
21488
|
+
|
|
21489
|
+
// onRemove() {
|
|
21490
|
+
// if (this._panel && this._panel.parentNode) {
|
|
21491
|
+
// this._panel.parentNode.removeChild(this._panel);
|
|
21492
|
+
// }
|
|
21493
|
+
// if (this._container && this._container.parentNode) {
|
|
21494
|
+
// this._container.parentNode.removeChild(this._container);
|
|
21495
|
+
// }
|
|
21496
|
+
// this._map = undefined;
|
|
21497
|
+
// }
|
|
21498
|
+
|
|
21499
|
+
// _togglePanel() {
|
|
21500
|
+
// this._isOpen ? this._closePanel() : this._openPanel();
|
|
21501
|
+
// }
|
|
21502
|
+
|
|
21503
|
+
// _openPanel() {
|
|
21504
|
+
// this._createPanelIfNeeded();
|
|
21505
|
+
|
|
21506
|
+
// const layers = this._map.getStyle().layers || [];
|
|
21507
|
+
// const rasterLayers = layers.filter(l => l.type === 'raster');
|
|
21508
|
+
|
|
21509
|
+
// this._tempLayers = rasterLayers.map(l => ({
|
|
21510
|
+
// id: l.id,
|
|
21511
|
+
// visible: this._map.getLayoutProperty(l.id, 'visibility') !== 'none'
|
|
21512
|
+
// }));
|
|
21513
|
+
|
|
21514
|
+
// this._renderLayerList();
|
|
21515
|
+
// this._panel.style.display = 'flex';
|
|
21516
|
+
// this._isOpen = true;
|
|
21517
|
+
// }
|
|
21518
|
+
|
|
21519
|
+
// _closePanel() {
|
|
21520
|
+
// if (this._panel) {
|
|
21521
|
+
// this._panel.style.display = 'none';
|
|
21522
|
+
// }
|
|
21523
|
+
// this._isOpen = false;
|
|
21524
|
+
// }
|
|
21525
|
+
|
|
21526
|
+
// _createPanelIfNeeded() {
|
|
21527
|
+
// if (this._panel) return;
|
|
21528
|
+
|
|
21529
|
+
// // 遮罩
|
|
21530
|
+
// this._panel = document.createElement('div');
|
|
21531
|
+
// this._panel.style.cssText = `
|
|
21532
|
+
// position: fixed;
|
|
21533
|
+
// top: 0; left: 0;
|
|
21534
|
+
// width: 100vw; height: 100vh;
|
|
21535
|
+
// background: rgba(0,0,0,0.45);
|
|
21536
|
+
// display: none;
|
|
21537
|
+
// align-items: center;
|
|
21538
|
+
// justify-content: center;
|
|
21539
|
+
// z-index: 10000;
|
|
21540
|
+
// `;
|
|
21541
|
+
|
|
21542
|
+
|
|
21543
|
+
// // 对话框
|
|
21544
|
+
// this._dialog = document.createElement('div');
|
|
21545
|
+
// this._dialog.style.cssText = `
|
|
21546
|
+
// position: relative;
|
|
21547
|
+
// background: #fff;
|
|
21548
|
+
// padding: 16px;
|
|
21549
|
+
// border-radius: 10px; /* 稍微更柔和 */
|
|
21550
|
+
// min-width: 320px;
|
|
21551
|
+
// max-width: 520px;
|
|
21552
|
+
// max-height: 75vh; /* 🔥 再低一点,留呼吸感 */
|
|
21553
|
+
// overflow: hidden; /* 防止整体溢出 */
|
|
21554
|
+
// display: flex;
|
|
21555
|
+
// flex-direction: column;
|
|
21556
|
+
// box-shadow: 0 6px 18px rgba(0,0,0,.22);
|
|
21557
|
+
// font-family: Arial, sans-serif;
|
|
21558
|
+
// `;
|
|
21559
|
+
|
|
21560
|
+
|
|
21561
|
+
|
|
21562
|
+
|
|
21563
|
+
// // 标题
|
|
21564
|
+
// const title = document.createElement('div');
|
|
21565
|
+
// title.textContent = '🗂 管理栅格底图';
|
|
21566
|
+
// title.style.cssText = `
|
|
21567
|
+
// font-weight: bold;
|
|
21568
|
+
// margin-bottom: 8px;
|
|
21569
|
+
// font-size: 15px;
|
|
21570
|
+
// `;
|
|
21571
|
+
|
|
21572
|
+
// // 列表容器
|
|
21573
|
+
// this._layerListContainer = document.createElement('div');
|
|
21574
|
+
// this._layerListContainer.style.cssText = `
|
|
21575
|
+
// width: 100%;
|
|
21576
|
+
// max-height: 50vh; /* 🔥 核心:最多占屏幕一半高度 */
|
|
21577
|
+
// overflow-y: auto; /* 🔥 超出滚动 */
|
|
21578
|
+
// overflow-x: hidden;
|
|
21579
|
+
// display: flex;
|
|
21580
|
+
// flex-direction: column;
|
|
21581
|
+
// gap: 6px;
|
|
21582
|
+
// padding: 4px 2px;
|
|
21583
|
+
// box-sizing: border-box;
|
|
21584
|
+
// border-top: 1px solid #eee;
|
|
21585
|
+
// border-bottom: 1px solid #eee;
|
|
21586
|
+
// `;
|
|
21587
|
+
|
|
21588
|
+
|
|
21589
|
+
|
|
21590
|
+
// this._dialog.appendChild(title);
|
|
21591
|
+
// this._dialog.appendChild(this._layerListContainer);
|
|
21592
|
+
// this._panel.appendChild(this._dialog);
|
|
21593
|
+
// document.body.appendChild(this._panel);
|
|
21594
|
+
|
|
21595
|
+
// // 点击遮罩关闭
|
|
21596
|
+
// this._panel.addEventListener('click', (e) => {
|
|
21597
|
+
// if (e.target === this._panel) this._closePanel();
|
|
21598
|
+
// });
|
|
21599
|
+
// }
|
|
21600
|
+
|
|
21601
|
+
// _renderLayerList() {
|
|
21602
|
+
// if (!this._layerListContainer) return;
|
|
21603
|
+
// this._layerListContainer.innerHTML = '';
|
|
21604
|
+
|
|
21605
|
+
// if (!this._tempLayers.length) {
|
|
21606
|
+
// this._layerListContainer.textContent = '无可选栅格图层';
|
|
21607
|
+
// return;
|
|
21608
|
+
// }
|
|
21609
|
+
|
|
21610
|
+
// this._tempLayers.forEach((layer, index) => {
|
|
21611
|
+
// const row = document.createElement('div');
|
|
21612
|
+
// row.style.cssText = `
|
|
21613
|
+
// display: flex;
|
|
21614
|
+
// align-items: center;
|
|
21615
|
+
// gap: 6px;
|
|
21616
|
+
// padding: 6px 8px;
|
|
21617
|
+
// background: #f8f9fa;
|
|
21618
|
+
// border-radius: 4px;
|
|
21619
|
+
// `;
|
|
21620
|
+
|
|
21621
|
+
// const checkbox = document.createElement('input');
|
|
21622
|
+
// checkbox.type = 'checkbox';
|
|
21623
|
+
// checkbox.checked = layer.visible;
|
|
21624
|
+
|
|
21625
|
+
// checkbox.onchange = () => {
|
|
21626
|
+
// layer.visible = checkbox.checked;
|
|
21627
|
+
|
|
21628
|
+
// // 🔥 立刻在地图中生效
|
|
21629
|
+
// this._map.setLayoutProperty(
|
|
21630
|
+
// layer.id,
|
|
21631
|
+
// 'visibility',
|
|
21632
|
+
// layer.visible ? 'visible' : 'none'
|
|
21633
|
+
// );
|
|
21634
|
+
|
|
21635
|
+
// // 🔄 同步按钮文字
|
|
21636
|
+
// this._updateButtonText();
|
|
21637
|
+
// };
|
|
21638
|
+
|
|
21639
|
+
|
|
21640
|
+
|
|
21641
|
+
// const label = document.createElement('span');
|
|
21642
|
+
// label.textContent = layer.id;
|
|
21643
|
+
// label.style.cssText = `
|
|
21644
|
+
// flex: 1;
|
|
21645
|
+
// font-size: 13px;
|
|
21646
|
+
// color: #333;
|
|
21647
|
+
// overflow: hidden;
|
|
21648
|
+
// text-overflow: ellipsis;
|
|
21649
|
+
// white-space: nowrap;
|
|
21650
|
+
// `;
|
|
21651
|
+
|
|
21652
|
+
// const upBtn = document.createElement('button');
|
|
21653
|
+
// upBtn.textContent = '↑';
|
|
21654
|
+
// upBtn.disabled = index === 0;
|
|
21655
|
+
// upBtn.onclick = () => this._moveTempLayer(index, index - 1);
|
|
21656
|
+
|
|
21657
|
+
// const downBtn = document.createElement('button');
|
|
21658
|
+
// downBtn.textContent = '↓';
|
|
21659
|
+
// downBtn.disabled = index === this._tempLayers.length - 1;
|
|
21660
|
+
// downBtn.onclick = () => this._moveTempLayer(index, index + 1);
|
|
21661
|
+
|
|
21662
|
+
// [upBtn, downBtn].forEach(btn => {
|
|
21663
|
+
// btn.style.cssText = `
|
|
21664
|
+
// padding: 2px 6px;
|
|
21665
|
+
// border: 1px solid #ccc;
|
|
21666
|
+
// background: #fff;
|
|
21667
|
+
// border-radius: 3px;
|
|
21668
|
+
// cursor: pointer;
|
|
21669
|
+
// `;
|
|
21670
|
+
// });
|
|
21671
|
+
|
|
21672
|
+
// row.appendChild(checkbox);
|
|
21673
|
+
// row.appendChild(label);
|
|
21674
|
+
// row.appendChild(upBtn);
|
|
21675
|
+
// row.appendChild(downBtn);
|
|
21676
|
+
// this._layerListContainer.appendChild(row);
|
|
21677
|
+
// });
|
|
21678
|
+
// }
|
|
21679
|
+
|
|
21680
|
+
// _moveTempLayer(from, to) {
|
|
21681
|
+
// const item = this._tempLayers.splice(from, 1)[0];
|
|
21682
|
+
// this._tempLayers.splice(to, 0, item);
|
|
21683
|
+
|
|
21684
|
+
// // ✅ 按 Mapbox 官方语义:从“最上层”往下重排
|
|
21685
|
+
// for (let i = this._tempLayers.length - 1; i >= 0; i--) {
|
|
21686
|
+
// const layerId = this._tempLayers[i].id;
|
|
21687
|
+
// const beforeId =
|
|
21688
|
+
// i === this._tempLayers.length - 1
|
|
21689
|
+
// ? undefined // 最上面的图层:移到最顶
|
|
21690
|
+
// : this._tempLayers[i + 1].id;
|
|
21691
|
+
|
|
21692
|
+
// // 关键防御:避免 moveLayer 自己到自己前面
|
|
21693
|
+
// if (beforeId && beforeId === layerId) continue;
|
|
21694
|
+
|
|
21695
|
+
// this._map.moveLayer(layerId, beforeId);
|
|
21696
|
+
// }
|
|
21697
|
+
|
|
21698
|
+
// this._renderLayerList();
|
|
21699
|
+
// }
|
|
21700
|
+
|
|
21701
|
+
|
|
21702
|
+
// _applyChanges() {
|
|
21703
|
+
// // 现在不再做任何地图操作,只是关闭面板
|
|
21704
|
+
// this._closePanel();
|
|
21705
|
+
// }
|
|
21706
|
+
|
|
21707
|
+
|
|
21708
|
+
// _updateButtonText() {
|
|
21709
|
+
// if (!this._map) return;
|
|
21710
|
+
|
|
21711
|
+
// const layers = this._map.getStyle().layers || [];
|
|
21712
|
+
// const rasterLayers = layers.filter(l => l.type === 'raster');
|
|
21713
|
+
|
|
21714
|
+
// let firstVisible = null;
|
|
21715
|
+
// for (const layer of rasterLayers) {
|
|
21716
|
+
// if (this._map.getLayoutProperty(layer.id, 'visibility') === 'visible') {
|
|
21717
|
+
// firstVisible = layer.id;
|
|
21718
|
+
// break;
|
|
21719
|
+
// }
|
|
21720
|
+
// }
|
|
21721
|
+
|
|
21722
|
+
// this._button.innerHTML = firstVisible
|
|
21723
|
+
// ? `底图:${firstVisible}`
|
|
21724
|
+
// : rasterLayers.length ? '底图:无' : '底图:无栅格图层';
|
|
21725
|
+
// }
|
|
21726
|
+
// }
|
|
21432
21727
|
class RasterLayerControl {
|
|
21433
21728
|
constructor() {
|
|
21434
21729
|
this._panel = null;
|
|
@@ -21659,18 +21954,30 @@ class RasterLayerControl {
|
|
|
21659
21954
|
downBtn.disabled = index === this._tempLayers.length - 1;
|
|
21660
21955
|
downBtn.onclick = () => this._moveTempLayer(index, index + 1);
|
|
21661
21956
|
|
|
21662
|
-
|
|
21663
|
-
|
|
21664
|
-
|
|
21665
|
-
|
|
21666
|
-
|
|
21667
|
-
|
|
21668
|
-
|
|
21669
|
-
|
|
21670
|
-
|
|
21957
|
+
// 定位按钮
|
|
21958
|
+
const locateBtn = document.createElement('button');
|
|
21959
|
+
locateBtn.textContent = '⊕';
|
|
21960
|
+
locateBtn.title = '定位到该图层';
|
|
21961
|
+
let locateInfo = null;
|
|
21962
|
+
try {
|
|
21963
|
+
locateInfo = this._getLayerLocateInfo(layer.id);
|
|
21964
|
+
} catch (e) {
|
|
21965
|
+
console.warn('获取图层定位信息失败:', layer.id, e);
|
|
21966
|
+
}
|
|
21967
|
+
if (!locateInfo) {
|
|
21968
|
+
locateBtn.disabled = true;
|
|
21969
|
+
locateBtn.style.opacity = '0.3';
|
|
21970
|
+
}
|
|
21971
|
+
locateBtn.onclick = () => this._locateToLayer(layer.id, locateBtn);
|
|
21972
|
+
|
|
21973
|
+
const btnStyle = `padding: 2px 6px; border: 1px solid #ccc; background: #fff; border-radius: 3px; cursor: pointer;`;
|
|
21974
|
+
upBtn.style.cssText = btnStyle;
|
|
21975
|
+
downBtn.style.cssText = btnStyle;
|
|
21976
|
+
locateBtn.style.cssText = locateInfo ? btnStyle : (btnStyle + ' opacity: 0.3; cursor: not-allowed;');
|
|
21671
21977
|
|
|
21672
21978
|
row.appendChild(checkbox);
|
|
21673
21979
|
row.appendChild(label);
|
|
21980
|
+
row.appendChild(locateBtn);
|
|
21674
21981
|
row.appendChild(upBtn);
|
|
21675
21982
|
row.appendChild(downBtn);
|
|
21676
21983
|
this._layerListContainer.appendChild(row);
|
|
@@ -21723,6 +22030,65 @@ class RasterLayerControl {
|
|
|
21723
22030
|
? `底图:${firstVisible}`
|
|
21724
22031
|
: rasterLayers.length ? '底图:无' : '底图:无栅格图层';
|
|
21725
22032
|
}
|
|
22033
|
+
|
|
22034
|
+
_getLayerLocateInfo(layerId) {
|
|
22035
|
+
if (!this._map) return null;
|
|
22036
|
+
const style = this._map.getStyle();
|
|
22037
|
+
const layer = style.layers.find(l => l.id === layerId);
|
|
22038
|
+
if (!layer || !layer.source) return null;
|
|
22039
|
+
const source = style.sources[layer.source];
|
|
22040
|
+
if (!source || !source.tiles || !source.tiles.length) return null;
|
|
22041
|
+
const tileUrl = source.tiles[0];
|
|
22042
|
+
// 提取后端基础地址
|
|
22043
|
+
let baseUrl = '';
|
|
22044
|
+
try {
|
|
22045
|
+
const u = new URL(tileUrl, window.location.origin);
|
|
22046
|
+
baseUrl = u.origin;
|
|
22047
|
+
} catch (e) {
|
|
22048
|
+
baseUrl = '';
|
|
22049
|
+
}
|
|
22050
|
+
// 动态栅格
|
|
22051
|
+
const dynMatch = tileUrl.match(/\/raster\/dynamic\/tile\/([^/]+)\//);
|
|
22052
|
+
if (dynMatch) return { type: 'dynamic', name: dynMatch[1], baseUrl };
|
|
22053
|
+
// mbtiles栅格
|
|
22054
|
+
const staticMatch = tileUrl.match(/\/raster\/([^/]+)\//);
|
|
22055
|
+
if (staticMatch && !tileUrl.includes('/dynamic/')) return { type: 'static', name: staticMatch[1], baseUrl };
|
|
22056
|
+
return null;
|
|
22057
|
+
}
|
|
22058
|
+
|
|
22059
|
+
async _locateToLayer(layerId, btn) {
|
|
22060
|
+
const info = this._getLayerLocateInfo(layerId);
|
|
22061
|
+
if (!info) return;
|
|
22062
|
+
const origText = btn.textContent;
|
|
22063
|
+
btn.textContent = '...';
|
|
22064
|
+
btn.disabled = true;
|
|
22065
|
+
try {
|
|
22066
|
+
let url = '';
|
|
22067
|
+
if (info.type === 'static') {
|
|
22068
|
+
url = `${info.baseUrl}/raster/center/${info.name}`;
|
|
22069
|
+
} else {
|
|
22070
|
+
url = `${info.baseUrl}/raster/dynamic/center/${info.name}`;
|
|
22071
|
+
}
|
|
22072
|
+
const resp = await fetch(url);
|
|
22073
|
+
if (!resp.ok) throw new Error('请求失败');
|
|
22074
|
+
const data = await resp.json();
|
|
22075
|
+
if (data.x != null && data.y != null) {
|
|
22076
|
+
this._map.flyTo({
|
|
22077
|
+
center: [data.x, data.y],
|
|
22078
|
+
zoom: data.zoom || 10,
|
|
22079
|
+
duration: 1500
|
|
22080
|
+
});
|
|
22081
|
+
this._closePanel();
|
|
22082
|
+
}
|
|
22083
|
+
} catch (e) {
|
|
22084
|
+
console.error('定位失败:', e);
|
|
22085
|
+
btn.textContent = '✕';
|
|
22086
|
+
setTimeout(() => { btn.textContent = origText; btn.disabled = false; }, 1500);
|
|
22087
|
+
return;
|
|
22088
|
+
}
|
|
22089
|
+
btn.textContent = origText;
|
|
22090
|
+
btn.disabled = false;
|
|
22091
|
+
}
|
|
21726
22092
|
}
|
|
21727
22093
|
|
|
21728
22094
|
// terrain-toggle-control.js
|