aboutsummaryrefslogtreecommitdiff
path: root/src/map/switcher/switcher.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/switcher/switcher.js')
-rw-r--r--src/map/switcher/switcher.js123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/map/switcher/switcher.js b/src/map/switcher/switcher.js
new file mode 100644
index 00000000..b6c62a6e
--- /dev/null
+++ b/src/map/switcher/switcher.js
@@ -0,0 +1,123 @@
+import './switcher.css';
+
+export class SwitcherControl {
+
+ constructor(onBeforeSwitch, onSwitch, onAfterSwitch) {
+ this.onBeforeSwitch = onBeforeSwitch;
+ this.onSwitch = onSwitch;
+ this.onAfterSwitch = onAfterSwitch;
+ this.onDocumentClick = this.onDocumentClick.bind(this);
+ this.styles = [];
+ this.currentStyle = null;
+ }
+
+ getDefaultPosition() {
+ return 'top-right';
+ }
+
+ updateStyles(updatedStyles, defaultStyle) {
+ this.styles = updatedStyles;
+
+ let selectedStyle = null;
+ for (const style of this.styles) {
+ if (style.id === (this.currentStyle || defaultStyle)) {
+ selectedStyle = style.id;
+ break;
+ }
+ }
+ if (!selectedStyle) {
+ selectedStyle = this.styles[0].id;
+ }
+
+ while (this.mapStyleContainer.firstChild) {
+ this.mapStyleContainer.removeChild(this.mapStyleContainer.firstChild);
+ }
+
+ let selectedStyleElement;
+
+ for (const style of this.styles) {
+ const styleElement = document.createElement('button');
+ styleElement.type = 'button';
+ styleElement.innerText = style.title;
+ styleElement.dataset.id = style.id;
+ styleElement.dataset.style = JSON.stringify(style.style);
+ styleElement.addEventListener('click', (event) => {
+ const { target } = event;
+ if (!target.classList.contains('active')) {
+ this.onSelectStyle(target);
+ }
+ });
+ if (style.id === selectedStyle) {
+ selectedStyleElement = styleElement;
+ styleElement.classList.add('active');
+ }
+ this.mapStyleContainer.appendChild(styleElement);
+ }
+
+ if (this.currentStyle !== selectedStyle) {
+ this.onSelectStyle(selectedStyleElement);
+ this.currentStyle = selectedStyle;
+ }
+ }
+
+ onSelectStyle(target) {
+ this.onBeforeSwitch();
+
+ const style = this.styles.find((it) => it.id === target.dataset.id);
+ this.map.setStyle(style.style, { diff: false });
+ this.map.setTransformRequest(style.transformRequest);
+
+ this.onSwitch(target.dataset.id);
+
+ this.mapStyleContainer.style.display = 'none';
+ this.styleButton.style.display = 'block';
+
+ const elements = this.mapStyleContainer.getElementsByClassName('active');
+ while (elements[0]) {
+ elements[0].classList.remove('active');
+ }
+ target.classList.add('active');
+
+ this.currentStyle = target.dataset.id;
+
+ this.onAfterSwitch();
+ }
+
+ onAdd(map) {
+ this.map = map;
+ this.controlContainer = document.createElement('div');
+ this.controlContainer.classList.add('maplibregl-ctrl');
+ this.controlContainer.classList.add('maplibregl-ctrl-group');
+ this.mapStyleContainer = document.createElement('div');
+ this.styleButton = document.createElement('button');
+ this.styleButton.type = 'button';
+ this.mapStyleContainer.classList.add('maplibregl-style-list');
+ this.styleButton.classList.add('maplibregl-ctrl-icon');
+ this.styleButton.classList.add('maplibregl-style-switcher');
+ this.styleButton.addEventListener('click', () => {
+ this.styleButton.style.display = 'none';
+ this.mapStyleContainer.style.display = 'block';
+ });
+ document.addEventListener('click', this.onDocumentClick);
+ this.controlContainer.appendChild(this.styleButton);
+ this.controlContainer.appendChild(this.mapStyleContainer);
+ return this.controlContainer;
+ }
+
+ onRemove() {
+ if (!this.controlContainer || !this.controlContainer.parentNode || !this.map || !this.styleButton) {
+ return;
+ }
+ this.styleButton.removeEventListener('click', this.onDocumentClick);
+ this.controlContainer.parentNode.removeChild(this.controlContainer);
+ document.removeEventListener('click', this.onDocumentClick);
+ this.map = undefined;
+ }
+
+ onDocumentClick(event) {
+ if (this.controlContainer && !this.controlContainer.contains(event.target) && this.mapStyleContainer && this.styleButton) {
+ this.mapStyleContainer.style.display = 'none';
+ this.styleButton.style.display = 'block';
+ }
+ }
+}