diff --git a/lib/www/client/source/src/views/Map.vue b/lib/www/client/source/src/views/Map.vue index 3eb779c..021a236 100644 --- a/lib/www/client/source/src/views/Map.vue +++ b/lib/www/client/source/src/views/Map.vue @@ -1299,18 +1299,47 @@ export default { const [ view, layers, crosshairs ] = hash.split(":"); if (view) { - const rx0 = /[xyzpb][+-]?[0-9]+\.?[0-9]*/g; - const rx1 = /([xyzpb])([+-]?[0-9]+\.?[0-9]*)/; - const key = {x: "longitude", y: "latitude", z: "zoom", p: "pitch", b: "bearing"}; + const entries = view + .split(/([xyzpb])/) + .filter( v => v.length ) + .reduce( (acc, cur, idx) => + (idx % 2 ? acc[acc.length-1].push(cur) : acc.push([cur]), acc), [] + ).map( ([k, v]) => [ key[k], Number(v) ] ) + .filter( ([k, v]) => k && !isNaN(v) ); + + this.viewState = Object.fromEntries(entries); - this.viewState = Object.fromEntries(view.match(rx0).map(i => i.match(rx1).slice(1, 3)).map(i => {i[0] = key[i[0]]; i[1] = Number(i[1]); return i})); } if (layers) { - const l = layers.split(";").filter(i => this.layersAvailable.hasOwnProperty(i)); - if (l.length) { - this.layerSelection = l; + const addLayers = []; + const remLayers = []; + const invLayers = []; + const setLayers = []; + + layers + .split(";") + .map( l => l.match(/([!+-])?(.+)/).slice(1) ) + .forEach( ([ action, name ]) => { + if (this.layersAvailable.hasOwnProperty(name)) { + const groupKeys = {"+": addLayers, "-": remLayers, "!": invLayers}; + const group = groupKeys[action] ?? setLayers; + group.push(name); + } + }); + + if (!addLayers.length && !remLayers.length && !invLayers.length && setLayers.length) { + // Set layers as per setLayers + this.layerSelection = [...setLayers]; + } else { + // Otherwise, ignore setLayers and use the current layerset + const layerset = new Set(this.layerSelection); + addLayers.forEach( layer => layerset.add(layer) ); + remLayers.forEach( layer => layerset.delete(layer) ); + invLayers.forEach( layer => + layerset.has(layer) ? layerset.delete(layer) : layerset.add(layer) ); + this.layerSelection = [...layerset]; } }