From 7b338688fb6f2bcca5236348495e4b7398f8de00 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Fri, 3 Sep 2021 20:38:43 -0700 Subject: Proper map localization --- modern/src/map/Map.js | 37 ++++++--------- modern/src/map/switcher/switcher.js | 91 +++++++++++++++++++++---------------- 2 files changed, 65 insertions(+), 63 deletions(-) diff --git a/modern/src/map/Map.js b/modern/src/map/Map.js index 2b95087..5e182a4 100644 --- a/modern/src/map/Map.js +++ b/modern/src/map/Map.js @@ -12,11 +12,7 @@ import { } from './mapStyles'; import { useAttributePreference } from '../common/preferences'; import palette from '../theme/palette'; - -// TODO fix localization -import en from '../../../web/l10n/en.json'; - -const t = (key) => en[key]; +import { useTranslation } from '../LocalizationProvider'; const element = document.createElement('div'); element.style.width = '100%'; @@ -24,7 +20,6 @@ element.style.height = '100%'; export const map = new maplibregl.Map({ container: element, - style: styleOsm(), }); let ready = false; @@ -66,23 +61,11 @@ const initMap = async () => { updateReadyValue(true); }; -map.on('load', initMap); - map.addControl(new maplibregl.NavigationControl({ showCompass: false, })); const switcher = new SwitcherControl( - [ - { title: t('mapOsm'), uri: styleOsm() }, - { title: t('mapCarto'), uri: styleCarto() }, - { title: t('mapMapboxStreets'), uri: styleMapbox('streets-v11') }, - { title: t('mapMapboxOutdoors'), uri: styleMapbox('outdoors-v11') }, - { title: t('mapMapboxSatellite'), uri: styleMapbox('satellite-v9') }, - { title: t('mapMapTilerBasic'), uri: styleMapTiler('basic', '{mapTilerKey}') }, - { title: t('mapMapTilerHybrid'), uri: styleMapTiler('hybrid', '{mapTilerKey}') }, - ], - t('mapOsm'), () => updateReadyValue(false), () => { const waiting = () => { @@ -100,19 +83,27 @@ map.addControl(switcher); const Map = ({ children }) => { const containerEl = useRef(null); + const t = useTranslation(); const [mapReady, setMapReady] = useState(false); const mapboxAccessToken = useAttributePreference('mapboxAccessToken'); + const mapTilerKey = useAttributePreference('mapTilerKey'); useEffect(() => { maplibregl.accessToken = mapboxAccessToken; }, [mapboxAccessToken]); - const mapTilerKey = useAttributePreference('mapTilerKey'); - useEffect(() => { - switcher.setVariable('mapTilerKey', mapTilerKey); + switcher.updateStyles([ + { id: 'osm', title: t('mapOsm'), uri: styleOsm() }, + { id: 'carto', title: t('mapCarto'), uri: styleCarto() }, + { id: 'mapboxStreets', title: t('mapMapboxStreets'), uri: styleMapbox('streets-v11') }, + { id: 'mapboxOutdoors', title: t('mapMapboxOutdoors'), uri: styleMapbox('outdoors-v11') }, + { id: 'mapboxSatellite', title: t('mapMapboxSatellite'), uri: styleMapbox('satellite-v9') }, + { id: 'mapTilerBasic', title: t('mapMapTilerBasic'), uri: styleMapTiler('basic', mapTilerKey) }, + { id: 'mapTilerHybrid', title: t('mapMapTilerHybrid'), uri: styleMapTiler('hybrid', mapTilerKey) }, + ], 'osm'); }, [mapTilerKey]); useEffect(() => { @@ -126,9 +117,7 @@ const Map = ({ children }) => { useLayoutEffect(() => { const currentEl = containerEl.current; currentEl.appendChild(element); - if (map) { - map.resize(); - } + map.resize(); return () => { currentEl.removeChild(element); }; diff --git a/modern/src/map/switcher/switcher.js b/modern/src/map/switcher/switcher.js index c239662..5fa62dc 100644 --- a/modern/src/map/switcher/switcher.js +++ b/modern/src/map/switcher/switcher.js @@ -1,63 +1,76 @@ export class SwitcherControl { - constructor(styles, defaultStyle, beforeSwitch, afterSwitch) { - this.styles = styles; - this.defaultStyle = defaultStyle; - this.beforeSwitch = beforeSwitch; - this.afterSwitch = afterSwitch; + + constructor(onBeforeSwitch, onAfterSwitch) { + this.onBeforeSwitch = onBeforeSwitch; + this.onAfterSwitch = onAfterSwitch; this.onDocumentClick = this.onDocumentClick.bind(this); - this.variables = {}; + this.styles = []; + this.currentStyle = null; } getDefaultPosition() { return 'top-right'; } - setVariable(key, value) { - this.variables[key] = value; - } + updateStyles(updatedStyles, selectedStyle) { + this.styles = updatedStyles; + + while (this.mapStyleContainer.firstChild) { + this.mapStyleContainer.removeChild(this.mapStyleContainer.firstChild); + } + + let selectedStyleElement; - 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'); for (const style of this.styles) { const styleElement = document.createElement('button'); styleElement.type = 'button'; styleElement.innerText = style.title; - if (style.title) { - styleElement.classList.add(style.title.replace(/[^a-z0-9-]/gi, '_')); - } + styleElement.dataset.id = style.id; styleElement.dataset.uri = JSON.stringify(style.uri); styleElement.addEventListener('click', (event) => { - const { srcElement } = event; - if (srcElement.classList.contains('active')) { - return; + const { target } = event; + if (!target.classList.contains('active')) { + this.onSelectStyle(target); } - this.beforeSwitch(); - let uri = JSON.parse(srcElement.dataset.uri); - if (typeof uri === 'string') { - Object.entries(this.variables).forEach(([key, value]) => uri = uri.replaceAll(`\{${key}}`, value)); - } - this.map.setStyle(uri); - this.afterSwitch(); - this.mapStyleContainer.style.display = 'none'; - this.styleButton.style.display = 'block'; - const elms = this.mapStyleContainer.getElementsByClassName('active'); - while (elms[0]) { - elms[0].classList.remove('active'); - } - srcElement.classList.add('active'); }); - if (style.title === this.defaultStyle) { + if (style.id === selectedStyle) { + selectedStyleElement = styleElement; styleElement.classList.add('active'); } this.mapStyleContainer.appendChild(styleElement); } + + if (this.currentStyle !== selectedStyle) { + this.onSelectStyle(selectedStyleElement); + } + } + + onSelectStyle(target) { + this.onBeforeSwitch(); + + this.map.setStyle(JSON.parse(target.dataset.uri)); + + 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.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', () => { -- cgit v1.2.3