raintee-maputils 1.0.34 → 1.0.35
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 +461 -150
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6561,245 +6561,543 @@ class RulerControl {
|
|
|
6561
6561
|
|
|
6562
6562
|
class CustomOptionsControl {
|
|
6563
6563
|
constructor(args) {
|
|
6564
|
-
const { options, onConfirm } = args;
|
|
6564
|
+
const { title, options, onConfirm } = args;
|
|
6565
6565
|
|
|
6566
|
-
this._container = null;
|
|
6567
6566
|
this._map = null;
|
|
6567
|
+
this._container = null;
|
|
6568
6568
|
|
|
6569
6569
|
this._options = options || [];
|
|
6570
|
+
this._title = title || '标题';
|
|
6570
6571
|
this._onConfirm = onConfirm || (() => { });
|
|
6571
|
-
|
|
6572
|
-
|
|
6573
|
-
console.error('请传入有效的 options 参数(数组)');
|
|
6574
|
-
}
|
|
6572
|
+
this._originalOptions = [...this._options];
|
|
6573
|
+
this._selectedOptions = [];
|
|
6575
6574
|
}
|
|
6576
6575
|
|
|
6577
6576
|
onAdd(map) {
|
|
6578
6577
|
this._map = map;
|
|
6579
6578
|
|
|
6580
|
-
// 创建控件外层容器
|
|
6581
6579
|
this._container = document.createElement('div');
|
|
6582
6580
|
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group custom-options-control';
|
|
6583
6581
|
|
|
6584
|
-
// 创建主按钮(初始只显示“三维模型”文字,点击展开)
|
|
6585
6582
|
const mainButton = document.createElement('button');
|
|
6583
|
+
mainButton.textContent = this._title;
|
|
6586
6584
|
mainButton.style.cssText = `
|
|
6587
|
-
|
|
6588
|
-
height: 100%;
|
|
6589
|
-
padding: 0.25rem 0.5rem;
|
|
6590
|
-
margin: 0;
|
|
6591
|
-
border: 1px solid #ccc;
|
|
6585
|
+
padding: 4px 8px;
|
|
6592
6586
|
background: white;
|
|
6593
|
-
border
|
|
6587
|
+
border: 1px solid #ccc;
|
|
6594
6588
|
cursor: pointer;
|
|
6595
|
-
font-size: 14px;
|
|
6596
|
-
text-align: left;
|
|
6597
6589
|
`;
|
|
6598
|
-
mainButton.textContent = '三维模型';
|
|
6599
|
-
mainButton.addEventListener('click', () => this._toggleExpanded());
|
|
6600
6590
|
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
6604
|
-
this._panel = document.createElement('div');
|
|
6605
|
-
this._panel.style.display = 'none';
|
|
6606
|
-
this._panel.style.padding = '10px';
|
|
6607
|
-
this._container.appendChild(this._panel);
|
|
6608
|
-
|
|
6609
|
-
// 创建选项列表和按钮组
|
|
6610
|
-
this._renderOptionsPanel();
|
|
6591
|
+
mainButton.addEventListener('click', () => {
|
|
6592
|
+
this._showModal();
|
|
6593
|
+
});
|
|
6611
6594
|
|
|
6595
|
+
this._container.appendChild(mainButton);
|
|
6612
6596
|
return this._container;
|
|
6613
6597
|
}
|
|
6614
6598
|
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
this._options.forEach((opt) => {
|
|
6630
|
-
const optionDiv = document.createElement('div');
|
|
6631
|
-
optionDiv.style.marginBottom = '6px';
|
|
6632
|
-
|
|
6633
|
-
const label = document.createElement('label');
|
|
6634
|
-
label.style.display = 'flex';
|
|
6635
|
-
label.style.alignItems = 'center';
|
|
6636
|
-
label.style.cursor = 'pointer';
|
|
6599
|
+
/** 创建遮罩弹窗 */
|
|
6600
|
+
_showModal() {
|
|
6601
|
+
// 创建遮罩层
|
|
6602
|
+
this._overlay = document.createElement('div');
|
|
6603
|
+
this._overlay.className = 'custom-modal-overlay';
|
|
6604
|
+
this._overlay.style.cssText = `
|
|
6605
|
+
position: fixed;
|
|
6606
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
6607
|
+
background: rgba(0,0,0,0.5);
|
|
6608
|
+
z-index: 9999;
|
|
6609
|
+
display: flex;
|
|
6610
|
+
justify-content: center;
|
|
6611
|
+
align-items: center;
|
|
6612
|
+
`;
|
|
6637
6613
|
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6614
|
+
// 弹窗容器
|
|
6615
|
+
this._modal = document.createElement('div');
|
|
6616
|
+
this._modal.className = 'custom-modal';
|
|
6617
|
+
this._modal.style.cssText = `
|
|
6618
|
+
width: 360px;
|
|
6619
|
+
max-height: 80vh;
|
|
6620
|
+
overflow: hidden;
|
|
6621
|
+
background: white;
|
|
6622
|
+
border-radius: 8px;
|
|
6623
|
+
padding: 20px;
|
|
6624
|
+
display: flex;
|
|
6625
|
+
flex-direction: column;
|
|
6626
|
+
`;
|
|
6642
6627
|
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6628
|
+
// 搜索框
|
|
6629
|
+
const searchInput = document.createElement('input');
|
|
6630
|
+
searchInput.placeholder = '搜索选项...';
|
|
6631
|
+
searchInput.className = 'custom-search-input';
|
|
6632
|
+
searchInput.style.cssText = `
|
|
6633
|
+
width: 100%;
|
|
6634
|
+
padding: 8px;
|
|
6635
|
+
border: 1px solid #ccc;
|
|
6636
|
+
border-radius: 4px;
|
|
6637
|
+
margin-bottom: 12px;
|
|
6638
|
+
`;
|
|
6639
|
+
searchInput.addEventListener('input', (e) => {
|
|
6640
|
+
this._renderList(e.target.value);
|
|
6641
|
+
});
|
|
6646
6642
|
|
|
6647
|
-
|
|
6648
|
-
span.textContent = opt.label;
|
|
6643
|
+
this._modal.appendChild(searchInput);
|
|
6649
6644
|
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6645
|
+
// 列表区域
|
|
6646
|
+
this._listBox = document.createElement('div');
|
|
6647
|
+
this._listBox.style.cssText = `
|
|
6648
|
+
flex: 1;
|
|
6649
|
+
overflow-y: auto;
|
|
6650
|
+
padding-right: 4px;
|
|
6651
|
+
`;
|
|
6652
|
+
this._modal.appendChild(this._listBox);
|
|
6655
6653
|
|
|
6656
|
-
//
|
|
6657
|
-
const
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6654
|
+
// 底部按钮
|
|
6655
|
+
const footer = document.createElement('div');
|
|
6656
|
+
footer.style.cssText = `
|
|
6657
|
+
margin-top: 12px;
|
|
6658
|
+
display: flex;
|
|
6659
|
+
justify-content: flex-end;
|
|
6660
|
+
gap: 8px;
|
|
6661
|
+
`;
|
|
6662
6662
|
|
|
6663
|
-
const
|
|
6664
|
-
|
|
6665
|
-
|
|
6663
|
+
const cancelBtn = document.createElement('button');
|
|
6664
|
+
cancelBtn.textContent = '取消';
|
|
6665
|
+
cancelBtn.style.cssText = `
|
|
6666
6666
|
padding: 6px 12px;
|
|
6667
6667
|
background: #ccc;
|
|
6668
6668
|
border: none;
|
|
6669
6669
|
border-radius: 4px;
|
|
6670
|
-
cursor: pointer;
|
|
6671
|
-
width: auto;
|
|
6672
6670
|
`;
|
|
6673
|
-
|
|
6671
|
+
cancelBtn.addEventListener('click', () => this._closeModal());
|
|
6674
6672
|
|
|
6675
|
-
const
|
|
6676
|
-
|
|
6677
|
-
|
|
6673
|
+
const okBtn = document.createElement('button');
|
|
6674
|
+
okBtn.textContent = '确定';
|
|
6675
|
+
okBtn.style.cssText = `
|
|
6678
6676
|
padding: 6px 12px;
|
|
6679
6677
|
background: #007cba;
|
|
6680
6678
|
color: white;
|
|
6681
6679
|
border: none;
|
|
6682
6680
|
border-radius: 4px;
|
|
6683
|
-
cursor: pointer;
|
|
6684
|
-
width: auto;
|
|
6685
6681
|
`;
|
|
6686
|
-
|
|
6682
|
+
okBtn.addEventListener('click', () => this._confirm());
|
|
6687
6683
|
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
this.
|
|
6691
|
-
}
|
|
6684
|
+
footer.appendChild(cancelBtn);
|
|
6685
|
+
footer.appendChild(okBtn);
|
|
6686
|
+
this._modal.appendChild(footer);
|
|
6692
6687
|
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
}
|
|
6688
|
+
this._overlay.appendChild(this._modal);
|
|
6689
|
+
document.body.appendChild(this._overlay);
|
|
6696
6690
|
|
|
6697
|
-
|
|
6698
|
-
|
|
6691
|
+
// 初始化列表
|
|
6692
|
+
this._renderList('');
|
|
6693
|
+
}
|
|
6699
6694
|
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6695
|
+
/** 搜索过滤 */
|
|
6696
|
+
_renderList(keyword) {
|
|
6697
|
+
this._listBox.innerHTML = '';
|
|
6698
|
+
|
|
6699
|
+
const list = keyword
|
|
6700
|
+
? this._originalOptions.filter(
|
|
6701
|
+
(o) =>
|
|
6702
|
+
o.label.toLowerCase().includes(keyword.toLowerCase()) ||
|
|
6703
|
+
String(o.value).toLowerCase().includes(keyword.toLowerCase())
|
|
6704
|
+
)
|
|
6705
|
+
: this._originalOptions;
|
|
6706
|
+
|
|
6707
|
+
if (list.length === 0) {
|
|
6708
|
+
const empty = document.createElement('div');
|
|
6709
|
+
empty.textContent = `未找到相关结果`;
|
|
6710
|
+
empty.style.textAlign = 'center';
|
|
6711
|
+
empty.style.padding = '20px';
|
|
6712
|
+
this._listBox.appendChild(empty);
|
|
6713
|
+
return;
|
|
6705
6714
|
}
|
|
6706
6715
|
|
|
6707
|
-
|
|
6716
|
+
list.forEach((opt) => {
|
|
6717
|
+
const item = document.createElement('label');
|
|
6718
|
+
item.style.cssText = `
|
|
6719
|
+
display: flex;
|
|
6720
|
+
align-items: center;
|
|
6721
|
+
padding: 6px 0;
|
|
6722
|
+
cursor: pointer;
|
|
6723
|
+
`;
|
|
6724
|
+
|
|
6725
|
+
const checkbox = document.createElement('input');
|
|
6726
|
+
checkbox.type = 'checkbox';
|
|
6727
|
+
checkbox.value = opt.value;
|
|
6728
|
+
checkbox.checked = this._selectedOptions.includes(opt.value);
|
|
6729
|
+
checkbox.style.marginRight = '8px';
|
|
6730
|
+
checkbox.addEventListener('change', () => this._toggle(opt.value));
|
|
6731
|
+
|
|
6732
|
+
const labelSpan = document.createElement('span');
|
|
6733
|
+
labelSpan.innerHTML = this._highlight(opt.label, keyword);
|
|
6734
|
+
|
|
6735
|
+
item.appendChild(checkbox);
|
|
6736
|
+
item.appendChild(labelSpan);
|
|
6737
|
+
|
|
6738
|
+
this._listBox.appendChild(item);
|
|
6739
|
+
});
|
|
6708
6740
|
}
|
|
6709
6741
|
|
|
6710
|
-
|
|
6711
|
-
|
|
6742
|
+
/** 高亮关键词 */
|
|
6743
|
+
_highlight(text, key) {
|
|
6744
|
+
if (!key) return text;
|
|
6745
|
+
return text.replace(new RegExp(`(${key})`, 'gi'), `<mark>$1</mark>`);
|
|
6746
|
+
}
|
|
6747
|
+
|
|
6748
|
+
/** 选择切换 */
|
|
6749
|
+
_toggle(value) {
|
|
6750
|
+
const index = this._selectedOptions.indexOf(value);
|
|
6751
|
+
if (index >= 0) this._selectedOptions.splice(index, 1);
|
|
6752
|
+
else this._selectedOptions.push(value);
|
|
6753
|
+
}
|
|
6712
6754
|
|
|
6755
|
+
/** 点击确定 */
|
|
6756
|
+
_confirm() {
|
|
6713
6757
|
this._onConfirm({
|
|
6714
|
-
selectedOptions: this._selectedOptions
|
|
6715
|
-
unselectedOptions: this.
|
|
6716
|
-
|
|
6758
|
+
selectedOptions: this._selectedOptions,
|
|
6759
|
+
unselectedOptions: this._originalOptions.filter(
|
|
6760
|
+
(o) => !this._selectedOptions.includes(o.value)
|
|
6761
|
+
),
|
|
6762
|
+
allOptions: this._originalOptions
|
|
6717
6763
|
});
|
|
6764
|
+
this._closeModal();
|
|
6718
6765
|
}
|
|
6719
6766
|
|
|
6720
|
-
|
|
6721
|
-
|
|
6767
|
+
/** 销毁弹窗 */
|
|
6768
|
+
_closeModal() {
|
|
6769
|
+
if (this._overlay) {
|
|
6770
|
+
document.body.removeChild(this._overlay);
|
|
6771
|
+
this._overlay = null;
|
|
6772
|
+
this._modal = null;
|
|
6773
|
+
}
|
|
6722
6774
|
}
|
|
6723
6775
|
|
|
6724
6776
|
onRemove() {
|
|
6725
|
-
if (this._container
|
|
6726
|
-
|
|
6727
|
-
}
|
|
6777
|
+
if (this._container) this._container.remove();
|
|
6778
|
+
this._closeModal();
|
|
6728
6779
|
}
|
|
6729
6780
|
}
|
|
6730
6781
|
|
|
6731
|
-
// 自定义控件类:ToggleControl
|
|
6782
|
+
// 自定义控件类:ToggleControl(带搜索过滤功能)
|
|
6732
6783
|
class CustomToggleControl {
|
|
6733
6784
|
/**
|
|
6734
6785
|
* 构造函数
|
|
6735
6786
|
* @param {Object} options
|
|
6736
|
-
* @param {string} options.name -
|
|
6737
|
-
* @param {string} options.field -
|
|
6738
|
-
* @param {boolean} options.defaultValue -
|
|
6739
|
-
* @param {string} options.svgIcon - SVG
|
|
6740
|
-
* @param {Function} [options.onToggle] -
|
|
6787
|
+
* @param {string} options.name - 控件名称
|
|
6788
|
+
* @param {string} options.field - 控制的字段名
|
|
6789
|
+
* @param {boolean} options.defaultValue - 默认值
|
|
6790
|
+
* @param {string} options.svgIcon - SVG 图标字符串
|
|
6791
|
+
* @param {Function} [options.onToggle] - 状态切换回调
|
|
6792
|
+
* @param {Array} [options.options] - 可选项目数组 [{id, name, icon?}]
|
|
6793
|
+
* @param {Function} [options.onOptionSelect] - 选项选择回调
|
|
6794
|
+
* @param {boolean} [options.showSearch] - 是否显示搜索框,默认 true
|
|
6741
6795
|
*/
|
|
6742
|
-
constructor({
|
|
6796
|
+
constructor({
|
|
6797
|
+
name,
|
|
6798
|
+
field,
|
|
6799
|
+
defaultValue = false,
|
|
6800
|
+
svgIcon,
|
|
6801
|
+
onToggle,
|
|
6802
|
+
options = [],
|
|
6803
|
+
onOptionSelect,
|
|
6804
|
+
showSearch = true
|
|
6805
|
+
}) {
|
|
6743
6806
|
this.name = name;
|
|
6744
6807
|
this.field = field;
|
|
6745
6808
|
this.defaultValue = defaultValue;
|
|
6746
6809
|
this.svgIcon = svgIcon;
|
|
6747
|
-
this.onToggle = onToggle;
|
|
6810
|
+
this.onToggle = onToggle;
|
|
6811
|
+
this.options = options; // 可选项目
|
|
6812
|
+
this.onOptionSelect = onOptionSelect; // 选项选择回调
|
|
6813
|
+
this.showSearch = showSearch; // 是否显示搜索框
|
|
6748
6814
|
|
|
6749
|
-
//
|
|
6815
|
+
// 控件状态
|
|
6750
6816
|
this._container = null;
|
|
6751
6817
|
this._button = null;
|
|
6752
|
-
this.
|
|
6818
|
+
this._dropdown = null;
|
|
6819
|
+
this._searchInput = null;
|
|
6820
|
+
this._optionsList = null;
|
|
6821
|
+
this.isActive = false;
|
|
6822
|
+
this.isDropdownOpen = false;
|
|
6823
|
+
this.filteredOptions = [...options]; // 过滤后的选项
|
|
6824
|
+
|
|
6825
|
+
// 绑定事件处理函数
|
|
6826
|
+
this._boundHandleClickOutside = this._handleClickOutside.bind(this);
|
|
6753
6827
|
}
|
|
6754
6828
|
|
|
6755
6829
|
// Mapbox 要求的 onAdd 方法
|
|
6756
6830
|
onAdd(map) {
|
|
6757
6831
|
this.map = map;
|
|
6758
6832
|
|
|
6759
|
-
// 创建外层容器
|
|
6833
|
+
// 创建外层容器
|
|
6760
6834
|
this._container = document.createElement('div');
|
|
6761
|
-
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group';
|
|
6835
|
+
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group custom-toggle-control';
|
|
6762
6836
|
|
|
6763
|
-
//
|
|
6837
|
+
// 创建主按钮
|
|
6764
6838
|
this._button = document.createElement('button');
|
|
6765
6839
|
this._button.type = 'button';
|
|
6766
6840
|
this._button.innerHTML = this.svgIcon;
|
|
6841
|
+
this._button.title = this.name;
|
|
6767
6842
|
|
|
6768
6843
|
// 设置按钮样式
|
|
6769
|
-
this.
|
|
6770
|
-
this._button.style.border = 'none';
|
|
6771
|
-
this._button.style.background = 'none';
|
|
6772
|
-
this._button.style.padding = '0';
|
|
6773
|
-
this._button.style.display = 'flex';
|
|
6774
|
-
this._button.style.alignItems = 'center';
|
|
6775
|
-
this._button.style.justifyContent = 'center';
|
|
6844
|
+
this._setupButtonStyles();
|
|
6776
6845
|
|
|
6777
6846
|
// 初始化状态
|
|
6778
6847
|
this.updateStatus();
|
|
6779
6848
|
|
|
6780
|
-
//
|
|
6781
|
-
this._button.addEventListener('click', () => {
|
|
6849
|
+
// 绑定事件
|
|
6850
|
+
this._button.addEventListener('click', (e) => {
|
|
6851
|
+
e.stopPropagation();
|
|
6782
6852
|
this.toggle();
|
|
6783
6853
|
});
|
|
6784
6854
|
|
|
6785
6855
|
this._container.appendChild(this._button);
|
|
6786
6856
|
|
|
6857
|
+
// 创建下拉菜单(如果有选项)
|
|
6858
|
+
if (this.options.length > 0) {
|
|
6859
|
+
this._createDropdown();
|
|
6860
|
+
}
|
|
6861
|
+
|
|
6787
6862
|
return this._container;
|
|
6788
6863
|
}
|
|
6789
6864
|
|
|
6790
|
-
//
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6865
|
+
// 设置按钮样式
|
|
6866
|
+
_setupButtonStyles() {
|
|
6867
|
+
Object.assign(this._button.style, {
|
|
6868
|
+
cursor: 'pointer',
|
|
6869
|
+
border: 'none',
|
|
6870
|
+
background: 'none',
|
|
6871
|
+
padding: '8px',
|
|
6872
|
+
display: 'flex',
|
|
6873
|
+
alignItems: 'center',
|
|
6874
|
+
justifyContent: 'center',
|
|
6875
|
+
borderRadius: '4px',
|
|
6876
|
+
transition: 'all 0.2s ease'
|
|
6877
|
+
});
|
|
6878
|
+
}
|
|
6879
|
+
|
|
6880
|
+
// 创建下拉菜单
|
|
6881
|
+
_createDropdown() {
|
|
6882
|
+
// 创建下拉容器
|
|
6883
|
+
this._dropdown = document.createElement('div');
|
|
6884
|
+
this._dropdown.className = 'custom-toggle-dropdown';
|
|
6885
|
+
Object.assign(this._dropdown.style, {
|
|
6886
|
+
position: 'absolute',
|
|
6887
|
+
top: '100%',
|
|
6888
|
+
right: '0',
|
|
6889
|
+
backgroundColor: 'white',
|
|
6890
|
+
border: '1px solid #ccc',
|
|
6891
|
+
borderRadius: '4px',
|
|
6892
|
+
boxShadow: '0 2px 10px rgba(0,0,0,0.1)',
|
|
6893
|
+
zIndex: '1000',
|
|
6894
|
+
minWidth: '200px',
|
|
6895
|
+
maxWidth: '300px',
|
|
6896
|
+
display: 'none',
|
|
6897
|
+
marginTop: '4px'
|
|
6898
|
+
});
|
|
6899
|
+
|
|
6900
|
+
// 创建搜索框(如果需要)
|
|
6901
|
+
if (this.showSearch && this.options.length > 5) {
|
|
6902
|
+
this._createSearchBox();
|
|
6794
6903
|
}
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
this.
|
|
6904
|
+
|
|
6905
|
+
// 创建选项列表
|
|
6906
|
+
this._createOptionsList();
|
|
6907
|
+
|
|
6908
|
+
this._container.appendChild(this._dropdown);
|
|
6909
|
+
}
|
|
6910
|
+
|
|
6911
|
+
// 创建搜索框
|
|
6912
|
+
_createSearchBox() {
|
|
6913
|
+
const searchContainer = document.createElement('div');
|
|
6914
|
+
Object.assign(searchContainer.style, {
|
|
6915
|
+
padding: '8px',
|
|
6916
|
+
borderBottom: '1px solid #eee'
|
|
6917
|
+
});
|
|
6918
|
+
|
|
6919
|
+
this._searchInput = document.createElement('input');
|
|
6920
|
+
this._searchInput.type = 'text';
|
|
6921
|
+
this._searchInput.placeholder = '搜索...';
|
|
6922
|
+
this._searchInput.style.cssText = `
|
|
6923
|
+
width: 100%;
|
|
6924
|
+
padding: 6px 8px;
|
|
6925
|
+
border: 1px solid #ddd;
|
|
6926
|
+
border-radius: 4px;
|
|
6927
|
+
fontSize: 12px;
|
|
6928
|
+
outline: none;
|
|
6929
|
+
box-sizing: border-box;
|
|
6930
|
+
`;
|
|
6931
|
+
|
|
6932
|
+
// 绑定搜索事件
|
|
6933
|
+
this._searchInput.addEventListener('input', (e) => {
|
|
6934
|
+
this._filterOptions(e.target.value);
|
|
6935
|
+
});
|
|
6936
|
+
|
|
6937
|
+
// 阻止下拉菜单关闭
|
|
6938
|
+
this._searchInput.addEventListener('click', (e) => {
|
|
6939
|
+
e.stopPropagation();
|
|
6940
|
+
});
|
|
6941
|
+
|
|
6942
|
+
searchContainer.appendChild(this._searchInput);
|
|
6943
|
+
this._dropdown.appendChild(searchContainer);
|
|
6798
6944
|
}
|
|
6799
6945
|
|
|
6800
|
-
//
|
|
6946
|
+
// 创建选项列表
|
|
6947
|
+
_createOptionsList() {
|
|
6948
|
+
this._optionsList = document.createElement('div');
|
|
6949
|
+
Object.assign(this._optionsList.style, {
|
|
6950
|
+
maxHeight: '200px',
|
|
6951
|
+
overflowY: 'auto',
|
|
6952
|
+
padding: '4px 0'
|
|
6953
|
+
});
|
|
6954
|
+
|
|
6955
|
+
this._renderOptionsList();
|
|
6956
|
+
this._dropdown.appendChild(this._optionsList);
|
|
6957
|
+
}
|
|
6958
|
+
|
|
6959
|
+
// 渲染选项列表
|
|
6960
|
+
_renderOptionsList() {
|
|
6961
|
+
if (!this._optionsList) return;
|
|
6962
|
+
|
|
6963
|
+
this._optionsList.innerHTML = '';
|
|
6964
|
+
|
|
6965
|
+
this.filteredOptions.forEach(option => {
|
|
6966
|
+
const optionItem = document.createElement('div');
|
|
6967
|
+
optionItem.className = 'custom-toggle-option';
|
|
6968
|
+
optionItem.dataset.id = option.id;
|
|
6969
|
+
|
|
6970
|
+
Object.assign(optionItem.style, {
|
|
6971
|
+
padding: '8px 12px',
|
|
6972
|
+
cursor: 'pointer',
|
|
6973
|
+
display: 'flex',
|
|
6974
|
+
alignItems: 'center',
|
|
6975
|
+
gap: '8px',
|
|
6976
|
+
fontSize: '13px',
|
|
6977
|
+
transition: 'background-color 0.2s'
|
|
6978
|
+
});
|
|
6979
|
+
|
|
6980
|
+
// 添加图标(如果有)
|
|
6981
|
+
if (option.icon) {
|
|
6982
|
+
const icon = document.createElement('span');
|
|
6983
|
+
icon.innerHTML = option.icon;
|
|
6984
|
+
icon.style.fontSize = '14px';
|
|
6985
|
+
optionItem.appendChild(icon);
|
|
6986
|
+
}
|
|
6987
|
+
|
|
6988
|
+
// 添加文本
|
|
6989
|
+
const text = document.createElement('span');
|
|
6990
|
+
text.textContent = option.name;
|
|
6991
|
+
optionItem.appendChild(text);
|
|
6992
|
+
|
|
6993
|
+
// 绑定点击事件
|
|
6994
|
+
optionItem.addEventListener('click', (e) => {
|
|
6995
|
+
e.stopPropagation();
|
|
6996
|
+
this._selectOption(option);
|
|
6997
|
+
});
|
|
6998
|
+
|
|
6999
|
+
// 鼠标悬停效果
|
|
7000
|
+
optionItem.addEventListener('mouseenter', () => {
|
|
7001
|
+
optionItem.style.backgroundColor = '#f5f5f5';
|
|
7002
|
+
});
|
|
7003
|
+
|
|
7004
|
+
optionItem.addEventListener('mouseleave', () => {
|
|
7005
|
+
optionItem.style.backgroundColor = 'transparent';
|
|
7006
|
+
});
|
|
7007
|
+
|
|
7008
|
+
this._optionsList.appendChild(optionItem);
|
|
7009
|
+
});
|
|
7010
|
+
|
|
7011
|
+
// 如果没有匹配的选项
|
|
7012
|
+
if (this.filteredOptions.length === 0) {
|
|
7013
|
+
const noResults = document.createElement('div');
|
|
7014
|
+
noResults.textContent = '无匹配项';
|
|
7015
|
+
Object.assign(noResults.style, {
|
|
7016
|
+
padding: '12px',
|
|
7017
|
+
textAlign: 'center',
|
|
7018
|
+
color: '#999',
|
|
7019
|
+
fontSize: '12px'
|
|
7020
|
+
});
|
|
7021
|
+
this._optionsList.appendChild(noResults);
|
|
7022
|
+
}
|
|
7023
|
+
}
|
|
7024
|
+
|
|
7025
|
+
// 过滤选项
|
|
7026
|
+
_filterOptions(searchTerm) {
|
|
7027
|
+
const term = searchTerm.toLowerCase().trim();
|
|
7028
|
+
|
|
7029
|
+
if (!term) {
|
|
7030
|
+
this.filteredOptions = [...this.options];
|
|
7031
|
+
} else {
|
|
7032
|
+
this.filteredOptions = this.options.filter(option =>
|
|
7033
|
+
option.name.toLowerCase().includes(term) ||
|
|
7034
|
+
(option.id && option.id.toString().toLowerCase().includes(term))
|
|
7035
|
+
);
|
|
7036
|
+
}
|
|
7037
|
+
|
|
7038
|
+
this._renderOptionsList();
|
|
7039
|
+
}
|
|
7040
|
+
|
|
7041
|
+
// 选择选项
|
|
7042
|
+
_selectOption(option) {
|
|
7043
|
+
// 调用选项选择回调
|
|
7044
|
+
if (this.onOptionSelect) {
|
|
7045
|
+
this.onOptionSelect(option);
|
|
7046
|
+
}
|
|
7047
|
+
|
|
7048
|
+
// 关闭下拉菜单
|
|
7049
|
+
this.closeDropdown();
|
|
7050
|
+
}
|
|
7051
|
+
|
|
7052
|
+
// 切换下拉菜单显示状态
|
|
7053
|
+
toggle() {
|
|
7054
|
+
if (this.isDropdownOpen) {
|
|
7055
|
+
this.closeDropdown();
|
|
7056
|
+
} else {
|
|
7057
|
+
this.openDropdown();
|
|
7058
|
+
}
|
|
7059
|
+
}
|
|
7060
|
+
|
|
7061
|
+
// 打开下拉菜单
|
|
7062
|
+
openDropdown() {
|
|
7063
|
+
if (!this._dropdown || this.options.length === 0) return;
|
|
7064
|
+
|
|
7065
|
+
this.isDropdownOpen = true;
|
|
7066
|
+
this._dropdown.style.display = 'block';
|
|
7067
|
+
|
|
7068
|
+
// 添加全局点击监听
|
|
7069
|
+
document.addEventListener('click', this._boundHandleClickOutside);
|
|
7070
|
+
|
|
7071
|
+
// 聚焦搜索框
|
|
7072
|
+
if (this._searchInput) {
|
|
7073
|
+
setTimeout(() => {
|
|
7074
|
+
this._searchInput.focus();
|
|
7075
|
+
this._searchInput.value = '';
|
|
7076
|
+
this._filterOptions('');
|
|
7077
|
+
}, 100);
|
|
7078
|
+
}
|
|
7079
|
+
}
|
|
7080
|
+
|
|
7081
|
+
// 关闭下拉菜单
|
|
7082
|
+
closeDropdown() {
|
|
7083
|
+
if (!this._dropdown) return;
|
|
7084
|
+
|
|
7085
|
+
this.isDropdownOpen = false;
|
|
7086
|
+
this._dropdown.style.display = 'none';
|
|
7087
|
+
|
|
7088
|
+
// 移除全局点击监听
|
|
7089
|
+
document.removeEventListener('click', this._boundHandleClickOutside);
|
|
7090
|
+
}
|
|
7091
|
+
|
|
7092
|
+
// 处理外部点击
|
|
7093
|
+
_handleClickOutside(event) {
|
|
7094
|
+
if (!this._container.contains(event.target)) {
|
|
7095
|
+
this.closeDropdown();
|
|
7096
|
+
}
|
|
7097
|
+
}
|
|
7098
|
+
|
|
7099
|
+
// 更新控件状态
|
|
6801
7100
|
updateStatus() {
|
|
6802
|
-
// 从 map.SourceMap 中获取当前 field 的值,如果不存在则使用 defaultValue
|
|
6803
7101
|
let currentValue = this.defaultValue;
|
|
6804
7102
|
|
|
6805
7103
|
if (
|
|
@@ -6810,21 +7108,22 @@ class CustomToggleControl {
|
|
|
6810
7108
|
currentValue = this.map.SourceMap[this.field];
|
|
6811
7109
|
}
|
|
6812
7110
|
|
|
6813
|
-
this.isActive = currentValue;
|
|
7111
|
+
this.isActive = currentValue;
|
|
6814
7112
|
|
|
6815
7113
|
// 更新按钮样式
|
|
6816
7114
|
if (this.isActive) {
|
|
6817
7115
|
this._button.style.opacity = '1';
|
|
6818
7116
|
this._button.style.filter = 'none';
|
|
7117
|
+
this._button.style.backgroundColor = '#e6f3ff';
|
|
6819
7118
|
} else {
|
|
6820
|
-
this._button.style.opacity = '0.
|
|
7119
|
+
this._button.style.opacity = '0.7';
|
|
6821
7120
|
this._button.style.filter = 'grayscale(100%)';
|
|
7121
|
+
this._button.style.backgroundColor = 'transparent';
|
|
6822
7122
|
}
|
|
6823
7123
|
}
|
|
6824
7124
|
|
|
6825
|
-
//
|
|
6826
|
-
|
|
6827
|
-
// 获取当前值
|
|
7125
|
+
// 切换状态(保持原有功能)
|
|
7126
|
+
toggleState() {
|
|
6828
7127
|
let currentValue = this.defaultValue;
|
|
6829
7128
|
|
|
6830
7129
|
if (
|
|
@@ -6835,22 +7134,34 @@ class CustomToggleControl {
|
|
|
6835
7134
|
currentValue = this.map.SourceMap[this.field];
|
|
6836
7135
|
}
|
|
6837
7136
|
|
|
6838
|
-
// 切换值
|
|
6839
7137
|
const newValue = !currentValue;
|
|
6840
7138
|
|
|
6841
|
-
// 更新到 map.SourceMap 中
|
|
6842
7139
|
if (this.map && this.map.SourceMap) {
|
|
6843
7140
|
this.map.SourceMap[this.field] = newValue;
|
|
6844
7141
|
}
|
|
6845
7142
|
|
|
6846
|
-
// 更新内部状态
|
|
6847
7143
|
this.isActive = newValue;
|
|
6848
|
-
|
|
6849
|
-
// 更新 UI 样式
|
|
6850
7144
|
this.updateStatus();
|
|
6851
7145
|
|
|
6852
|
-
|
|
6853
|
-
|
|
7146
|
+
if (this.onToggle) {
|
|
7147
|
+
this.onToggle(newValue);
|
|
7148
|
+
}
|
|
7149
|
+
}
|
|
7150
|
+
|
|
7151
|
+
// Mapbox 要求的 onRemove 方法
|
|
7152
|
+
onRemove() {
|
|
7153
|
+
this.closeDropdown();
|
|
7154
|
+
|
|
7155
|
+
if (this._container && this._container.parentNode) {
|
|
7156
|
+
this._container.parentNode.removeChild(this._container);
|
|
7157
|
+
}
|
|
7158
|
+
|
|
7159
|
+
this.map = null;
|
|
7160
|
+
this._container = null;
|
|
7161
|
+
this._button = null;
|
|
7162
|
+
this._dropdown = null;
|
|
7163
|
+
this._searchInput = null;
|
|
7164
|
+
this._optionsList = null;
|
|
6854
7165
|
}
|
|
6855
7166
|
}
|
|
6856
7167
|
|