From 4a8d9587363925aaf8a1525d7177fb84b5f3e6de Mon Sep 17 00:00:00 2001 From: azarz Date: Fri, 22 Dec 2023 16:51:35 +0100 Subject: [PATCH] feat(compare): true compare mode --- src/css/app.scss | 1 + .../map-buttons/compare/compare-fade.svg | 11 + .../compare/compare-layer-left.svg | 24 ++ .../compare/compare-layer-right.svg | 24 ++ .../map-buttons/compare/compare-leftright.svg | 14 + .../map-buttons/compare/compare-slider.svg | 5 + .../map-buttons/compare/compare-updown.svg | 14 + .../map-buttons/{ => compare}/compare.svg | 0 src/css/compare.css | 65 ++++ src/css/layer-catalogue.css | 5 - src/css/map-buttons.css | 77 ++++- src/css/map.css | 8 + src/html/index.html | 2 + src/html/map.html | 3 +- src/html/mapButtons.html | 14 + src/html/tabs/compareLayers1Window.html | 3 + src/html/tabs/compareLayers2Window.html | 3 + src/js/compare.js | 292 ++++++++++++++++-- src/js/controls.js | 10 + src/js/data-layer/layers-config.json | 14 +- src/js/dom.js | 10 + src/js/globals.js | 8 +- src/js/index.js | 31 +- src/js/layer-manager/layer-catalogue.js | 150 +++------ src/js/layer-manager/layer-group.js | 13 +- src/js/map-buttons-listeners.js | 2 +- .../interactivity-indicator.js | 4 +- src/js/nav.js | 80 ++++- src/js/route-draw/route-draw.js | 2 +- src/js/state.js | 9 + 30 files changed, 725 insertions(+), 173 deletions(-) create mode 100644 src/css/assets/map-buttons/compare/compare-fade.svg create mode 100644 src/css/assets/map-buttons/compare/compare-layer-left.svg create mode 100644 src/css/assets/map-buttons/compare/compare-layer-right.svg create mode 100644 src/css/assets/map-buttons/compare/compare-leftright.svg create mode 100644 src/css/assets/map-buttons/compare/compare-slider.svg create mode 100644 src/css/assets/map-buttons/compare/compare-updown.svg rename src/css/assets/map-buttons/{ => compare}/compare.svg (100%) create mode 100644 src/css/compare.css create mode 100644 src/html/tabs/compareLayers1Window.html create mode 100644 src/html/tabs/compareLayers2Window.html diff --git a/src/css/app.scss b/src/css/app.scss index 8b3dcd4a..6a31e209 100644 --- a/src/css/app.scss +++ b/src/css/app.scss @@ -16,4 +16,5 @@ @use 'layer-switcher.css'; @use 'my-account.css'; @use 'poi.css'; +@use 'compare.css'; @use 'media-queries.css'; diff --git a/src/css/assets/map-buttons/compare/compare-fade.svg b/src/css/assets/map-buttons/compare/compare-fade.svg new file mode 100644 index 00000000..d2d71301 --- /dev/null +++ b/src/css/assets/map-buttons/compare/compare-fade.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/css/assets/map-buttons/compare/compare-layer-left.svg b/src/css/assets/map-buttons/compare/compare-layer-left.svg new file mode 100644 index 00000000..77a94dee --- /dev/null +++ b/src/css/assets/map-buttons/compare/compare-layer-left.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/css/assets/map-buttons/compare/compare-layer-right.svg b/src/css/assets/map-buttons/compare/compare-layer-right.svg new file mode 100644 index 00000000..2f8bcaa3 --- /dev/null +++ b/src/css/assets/map-buttons/compare/compare-layer-right.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/css/assets/map-buttons/compare/compare-leftright.svg b/src/css/assets/map-buttons/compare/compare-leftright.svg new file mode 100644 index 00000000..fb1b9113 --- /dev/null +++ b/src/css/assets/map-buttons/compare/compare-leftright.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/css/assets/map-buttons/compare/compare-slider.svg b/src/css/assets/map-buttons/compare/compare-slider.svg new file mode 100644 index 00000000..579653d5 --- /dev/null +++ b/src/css/assets/map-buttons/compare/compare-slider.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/css/assets/map-buttons/compare/compare-updown.svg b/src/css/assets/map-buttons/compare/compare-updown.svg new file mode 100644 index 00000000..dea3ea65 --- /dev/null +++ b/src/css/assets/map-buttons/compare/compare-updown.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/css/assets/map-buttons/compare.svg b/src/css/assets/map-buttons/compare/compare.svg similarity index 100% rename from src/css/assets/map-buttons/compare.svg rename to src/css/assets/map-buttons/compare/compare.svg diff --git a/src/css/compare.css b/src/css/compare.css new file mode 100644 index 00000000..6a45906f --- /dev/null +++ b/src/css/compare.css @@ -0,0 +1,65 @@ +.layerSelectorDiv { + height: 32px; + margin-top: 25px; + padding-bottom: 16px; + border-bottom: 1px solid #DDE1E6; + margin-bottom: 24px; + display: flex; + justify-content: center; + align-items: center; + font-size: 14px; +} + +.layerSelectorDiv > .toggleSwitch { + margin: 0 12px; +} + +.layerSelectorDiv > .toggleSwitch > .toggleSlider { + background-color: #26A581; +} + +.subCategoryRLTLayer { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-around; +} + +.subCategoryRLTLayer .layer .layerImg img { + width: 100%; + aspect-ratio: 3 / 2; + object-fit: cover; + border-radius: 2px; +} + +.rltLayer { + display: inline-block; + width: 40%; + margin-bottom: 10px; +} + +.rltLayer > .layer-title { + font-size: 12px; + font-weight: 600; +} + +.maplibregl-compare { + position: fixed; +} + +.maplibregl-compare .compare-swiper-vertical { + background-color: white; + background-image: url(assets/map-buttons/compare/compare-slider.svg); + background-position: center; + background-repeat: no-repeat; + touch-action: none; +} + +.maplibregl-compare .compare-swiper-horizontal { + transform:rotate(90deg) translate(0, 50%); + background-color: white; + background-image: url(assets/map-buttons/compare/compare-slider.svg); + background-position: center; + background-repeat: no-repeat; + touch-action: none; +} \ No newline at end of file diff --git a/src/css/layer-catalogue.css b/src/css/layer-catalogue.css index c3e729b1..f79123d7 100644 --- a/src/css/layer-catalogue.css +++ b/src/css/layer-catalogue.css @@ -94,11 +94,6 @@ box-sizing: border-box; } -.comparedLayer img { - border: solid 5px #0b6ba7; - box-sizing: border-box; -} - #baseLayers .layer { display: inline-block; padding-bottom: 1em; diff --git a/src/css/map-buttons.css b/src/css/map-buttons.css index cc1e2086..3ff0cad3 100644 --- a/src/css/map-buttons.css +++ b/src/css/map-buttons.css @@ -39,12 +39,87 @@ } #sideBySideBtn { - background-image: url("assets/map-buttons/compare.svg"); + background-image: url("assets/map-buttons/compare/compare.svg"); position: absolute; left: 15px; bottom: 0; } +#sideBySideLeftLayer { + background-image: url("assets/map-buttons/compare/compare-layer-left.svg"); + position: absolute; + left: 15px; + bottom: 0; +} + +#sideBySideRightLayer { + background-image: url("assets/map-buttons/compare/compare-layer-right.svg"); + position: absolute; + right: 15px; + bottom: 0; +} + +#compareMode { + position: fixed; + top: calc(10px + env(safe-area-inset-top)); + right: calc(15px + env(safe-area-inset-left)); + width: 120px; + height: 40px; + display: flex; + flex-direction: row; + z-index: 2; +} + +#compareMode > div { + width: 40px; + height: 40px; + background-position: center; + background-repeat: no-repeat; + background-size: 40px; + filter: grayscale(1); +} + +#compareMode > div.selected { + filter: grayscale(0); +} + +#compareLeftRight { + background-image: url("assets/map-buttons/compare/compare-leftright.svg"); +} + +#compareUpDown { + background-image: url("assets/map-buttons/compare/compare-updown.svg"); +} + +#compareFade { + background-image: url("assets/map-buttons/compare/compare-fade.svg"); +} + +#sideBySideFadeSlider { + width: calc(100vw - 144px - env(safe-area-inset-left) - env(safe-area-inset-right)); + position: absolute; + z-index: 2; + height: 42px; + background-color: white; + bottom: 0; + left: 50%; + transform: translate(-50%); + border-radius: 5px; + display: flex; + justify-content: center; + align-items: center; +} + +#sideBySideFadeSlider-range { + width: 100%; + margin: 0 26px; +} + +#sideBySideFadeSlider-range-input { + width: 100%; + background: white; +} + #compassBtn { background-image: url("assets/map-buttons/compass.svg"); position: absolute; diff --git a/src/css/map.css b/src/css/map.css index 21bd4041..2232a50d 100644 --- a/src/css/map.css +++ b/src/css/map.css @@ -36,6 +36,14 @@ position: fixed; } +.mapRLT { + height: 100vh; +} + +#mapRLT1 { + z-index: 1; +} + #cartoContainer { min-height: 100vh; display: flex; diff --git a/src/html/index.html b/src/html/index.html index 6474ecd9..f6c0e2df 100644 --- a/src/html/index.html +++ b/src/html/index.html @@ -44,6 +44,8 @@ <%= require('html-loader!./tabs/myaccountWindow.html').default %> <%= require('html-loader!./tabs/informationsWindow.html').default %> <%= require('html-loader!./tabs/poiWindow.html').default %> + <%= require('html-loader!./tabs/compareLayers1Window.html').default %> + <%= require('html-loader!./tabs/compareLayers2Window.html').default %> diff --git a/src/html/map.html b/src/html/map.html index 3be4644d..cac64e43 100644 --- a/src/html/map.html +++ b/src/html/map.html @@ -1,4 +1,5 @@
-
+
+
diff --git a/src/html/mapButtons.html b/src/html/mapButtons.html index ea9d7838..5745da24 100644 --- a/src/html/mapButtons.html +++ b/src/html/mapButtons.html @@ -2,6 +2,13 @@
Filtres
+ +
+
+
+
+
+
@@ -13,6 +20,13 @@
+
+
+
+
+ +
+
diff --git a/src/html/tabs/compareLayers1Window.html b/src/html/tabs/compareLayers1Window.html new file mode 100644 index 00000000..eff89d92 --- /dev/null +++ b/src/html/tabs/compareLayers1Window.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/html/tabs/compareLayers2Window.html b/src/html/tabs/compareLayers2Window.html new file mode 100644 index 00000000..6336e622 --- /dev/null +++ b/src/html/tabs/compareLayers2Window.html @@ -0,0 +1,3 @@ +
+ +
diff --git a/src/js/compare.js b/src/js/compare.js index 8d97cadf..4b80442c 100644 --- a/src/js/compare.js +++ b/src/js/compare.js @@ -1,7 +1,12 @@ -import maplibregl from "maplibre-gl"; import MapLibreGlCompare from "@maplibre/maplibre-gl-compare"; import Globals from './globals'; +import DOM from './dom'; +import LayersConfig from './layer-manager/layer-config'; +import LayersAdditional from './layer-manager/layer-additional'; + +import ImageNotFound from '../html/img/image-not-found.png'; + /** * Outil de comparaison de carte @@ -18,34 +23,283 @@ class Compare { this.prevDataLayerDisplayed = ''; this.container = "#cartoContainer"; this.map = Globals.map; - this.mapRLT = Globals.mapRLT; + this.mapRLT1 = Globals.mapRLT1; + this.mapRLT2 = Globals.mapRLT2; + this.fadeSliderInput = document.getElementById("sideBySideFadeSlider-range-input"); + + // one of "leftright", "updown", "fade" + this.mode = "leftright"; this.actived = false; + this.#render(); + this.#listeners(); + return this; } + /** + * rendu graphique du contrôle + */ + #render() { + var targets = [DOM.$compareLayers1Window, DOM.$compareLayers2Window]; + + for (let i=0; i < targets.length; i++) { + let target = targets[i]; + const tplLayer = (opts) => { + return ` +
+
+ ${opts.layerName} +
+
+
${opts.layerThematic}
+
${opts.layerTitle}
+
+ `; + } + + var strRLTLayersPhotos = ""; + var strRLTLayersMaps = ""; + var rltLayers = LayersConfig.getRLTLayers(); + for(let j = 0; j < rltLayers.length; j++) { + var props = LayersConfig.getLayerProps(rltLayers[j]); + if (rltLayers[j].split(".")[0] == "ORTHOIMAGERY") { + if (rltLayers[j] == "ORTHOIMAGERY.ORTHOPHOTOS$GEOPORTAIL:OGC:WMTS") { + props.title = "Aujourd'hui" + } + strRLTLayersPhotos += tplLayer({ + type : "rltLayer", + layerID : rltLayers[j], + layerName : props.layer, + layerQuickLook : LayersAdditional.getQuickLookUrl(props.layer), + layerTitle : props.title, + layerThematic : "" + }); + } else { + strRLTLayersMaps += tplLayer({ + type : "rltLayer", + layerID : rltLayers[j], + layerName : props.layer, + layerQuickLook : LayersAdditional.getQuickLookUrl(props.layer), + layerTitle : props.title, + layerThematic : "" + }); + } + } + + var templateToggle = ` +
+ Photos + + Cartes +
`; + var templateLayers = ` +
+
+ ${strRLTLayersPhotos} +
+
+ ${strRLTLayersMaps} +
+
`; + + const stringToHTML = (str) => { + var support = function () { + if (!window.DOMParser) return false; + var parser = new DOMParser(); + try { + parser.parseFromString('x', 'text/html'); + } catch (err) { + return false; + } + return true; + }; + + // If DOMParser is supported, use it + if (support()) { + var parser = new DOMParser(); + var doc = parser.parseFromString(str, 'text/html'); + return doc.body.firstChild; + } + + // Otherwise, fallback to old-school method + var dom = document.createElement('div'); + dom.innerHTML = str; + return dom; + + }; + + // transformation du container : String -> DOM + var containerToggle = stringToHTML(templateToggle.trim()); + var containerLayers = stringToHTML(templateLayers.trim()); + + if (!containerLayers) { + console.warn(); + return; + } + + target.appendChild(containerToggle); + target.appendChild(containerLayers); + } + } + + /** + * Ajoute les écouteurs d'évènements + */ + #listeners() { + document.querySelector("#compareLeftRight").addEventListener("click", () => { + this.mode = "leftright"; + this.#changeMode(); + });; + document.querySelector("#compareUpDown").addEventListener("click", () => { + this.mode = "upDown"; + this.#changeMode(); + }); + document.querySelector("#compareFade").addEventListener("click", () => { + this.mode = "fade"; + this.#changeMode(); + }); + + this.fadeSliderInput.addEventListener('input', () => this.fadeSliderInput.style.setProperty('--value', this.fadeSliderInput.value)); + this.fadeSliderInput.addEventListener('input', () => { + document.getElementById("mapRLT1").style.opacity = this.fadeSliderInput.value / 100; + }); + + document.getElementById("rltMapToggle1").addEventListener("change", (e) => { + if (e.target.checked) { + document.getElementById("RLTphotoLayers1").classList.add("d-none"); + document.getElementById("RLTmapLayers1").classList.remove("d-none"); + } else { + document.getElementById("RLTphotoLayers1").classList.remove("d-none"); + document.getElementById("RLTmapLayers1").classList.add("d-none"); + } + }); + document.getElementById("rltMapToggle2").addEventListener("change", (e) => { + if (e.target.checked) { + document.getElementById("RLTphotoLayers2").classList.add("d-none"); + document.getElementById("RLTmapLayers2").classList.remove("d-none"); + } else { + document.getElementById("RLTphotoLayers2").classList.remove("d-none"); + document.getElementById("RLTmapLayers2").classList.add("d-none"); + } + }); + + DOM.$sideBySideLeftLayer.addEventListener("click", () => { + if (Globals.backButtonState == "compareLayers2") { + Globals.menu.close("compareLayers2"); + } + Globals.menu.open("compareLayers1"); + }); + + DOM.$sideBySideRightLayer.addEventListener("click", () => { + if (Globals.backButtonState == "compareLayers1") { + Globals.menu.close("compareLayers1"); + } + Globals.menu.open("compareLayers2"); + }); + + // clic sur une rlt de fonds + document.querySelectorAll(".rltLayer").forEach((el) => { + el.addEventListener('click', (e) => { + if (el.classList.contains("selectedLayer")) { + return; + } else { + document.querySelectorAll(`.rltLayer.mapRLT${el.dataset.map}`).forEach((elem) => { + elem.classList.remove("selectedLayer"); + }); + el.classList.add("selectedLayer"); + this.#addLayer(el.dataset.layerid, el.dataset.map); + } + }); + }); + } + + /** + * ajoute un layer à une map + */ + #addLayer(layerid, mapid) { + const layer = { + id : "maplayer", + source : layerid, + type : "raster" + }; + + if (mapid === "1") { + if(this.mapRLT1.getLayer("maplayer")) { + this.mapRLT1.removeLayer("maplayer"); + } + Globals.comparedLayers[0] = layerid; + this.mapRLT1.addLayer(layer); + } else if (mapid === "2") { + if(this.mapRLT2.getLayer("maplayer")) { + this.mapRLT2.removeLayer("maplayer"); + } + Globals.comparedLayers[1] = layerid; + this.mapRLT2.addLayer(layer); + } + } + + /** + * change le mode de comparaison + */ + #changeMode() { + document.querySelector("#compareLeftRight").classList.remove("selected"); + document.querySelector("#compareUpDown").classList.remove("selected"); + document.querySelector("#compareFade").classList.remove("selected"); + + if (this.mode == "leftright") { + document.querySelector("#compareLeftRight").classList.add("selected"); + document.querySelector("#sideBySideFadeSlider").classList.add("d-none"); + this.fadeSliderInput.value = 100; + this.fadeSliderInput.style.setProperty('--value', 100) + document.getElementById("mapRLT1").style.removeProperty("opacity"); + if (this.sideBySide) { + this.sideBySide.remove(); + } + this.sideBySide = new MapLibreGlCompare(this.mapRLT1, this.mapRLT2, this.container, {orientation: "vertical"}); + } else if (this.mode == "upDown") { + document.querySelector("#compareUpDown").classList.add("selected"); + document.querySelector("#sideBySideFadeSlider").classList.add("d-none"); + this.fadeSliderInput.value = 100; + this.fadeSliderInput.style.setProperty('--value', 100) + document.getElementById("mapRLT1").style.removeProperty("opacity"); + if (this.sideBySide) { + this.sideBySide.remove(); + } + this.sideBySide = new MapLibreGlCompare(this.mapRLT1, this.mapRLT2, this.container, {orientation: "horizontal"}); + } else if (this.mode == "fade") { + document.querySelector("#compareFade").classList.add("selected"); + if (this.sideBySide) { + this.sideBySide.remove(); + } + document.querySelector("#sideBySideFadeSlider").classList.remove("d-none"); + } + } + /** * active la comparaison * @public */ show() { this.actived = true; + this.mode = "leftright"; + document.querySelector("#map").classList.add("d-none"); + document.querySelector("#mapRLT1").classList.remove("d-none"); + document.querySelector("#mapRLT2").classList.remove("d-none"); + document.getElementById(`mapRLT1-${Globals.comparedLayers[0]}`).click(); + document.getElementById(`mapRLT2-${Globals.comparedLayers[1]}`).click(); - document.querySelector("#mapRLT").classList.remove("d-none"); - - this.mapRLT.setCenter(this.map.getCenter()); - this.mapRLT.setZoom(this.map.getZoom()); - - this.sideBySide = new MapLibreGlCompare(this.map, this.mapRLT, this.container); + this.mapRLT1.setCenter(this.map.getCenter()); + this.mapRLT2.setCenter(this.map.getCenter()); + this.mapRLT1.setZoom(this.map.getZoom()); + this.mapRLT2.setZoom(this.map.getZoom()); + this.#changeMode(); Globals.mapState = "compare"; - document.querySelector(".baseLayer:not(.selectedLayer)").click(); - - this.prevDataLayerDisplayed = Globals.dataLayerDisplayed; - - document.querySelector(".selectedLayer").style.pointerEvents = "none"; - Globals.menu.open("layerManager"); } /** @@ -56,16 +310,18 @@ class Compare { this.actived = false; Globals.menu.close("layerManager"); + document.querySelector("#sideBySideFadeSlider").classList.add("d-none"); - document.querySelectorAll(".baseLayer").forEach(elem => { - elem.classList.remove('comparedLayer'); - }); document.querySelector(".selectedLayer").style.pointerEvents = ""; if (this.sideBySide) { this.sideBySide.remove(); } + this.map.setCenter(this.mapRLT1.getCenter()); + this.map.setZoom(this.mapRLT1.getZoom()); Globals.mapState = "default"; - document.querySelector("#mapRLT").classList.add("d-none"); + document.querySelector("#map").classList.remove("d-none"); + document.querySelector("#mapRLT1").classList.add("d-none"); + document.querySelector("#mapRLT2").classList.add("d-none"); } /** diff --git a/src/js/controls.js b/src/js/controls.js index 3510c1be..b97289bd 100644 --- a/src/js/controls.js +++ b/src/js/controls.js @@ -67,6 +67,16 @@ const addControls = () => { unit: 'metric' }), "bottom-left"); + Globals.mapRLT1.addControl(new maplibregl.ScaleControl({ + maxWidth: 150, + unit: 'metric' + }), "bottom-left"); + + Globals.mapRLT2.addControl(new maplibregl.ScaleControl({ + maxWidth: 150, + unit: 'metric' + }), "bottom-left"); + // contrôle filtres POI Globals.poi = new POI(map, {}); Globals.poi.load() // promise ! diff --git a/src/js/data-layer/layers-config.json b/src/js/data-layer/layers-config.json index 6fbe2c1e..351a1eae 100644 --- a/src/js/data-layer/layers-config.json +++ b/src/js/data-layer/layers-config.json @@ -45,7 +45,7 @@ "layers": { "GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2$GEOPORTAIL:OGC:WMTS": { "name": "GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2", - "title": "Plan IGN", + "title": "Aujourd'hui", "description": "Cartographie multi-échelles sur le territoire national, issue des bases de données vecteur de l’IGN, mis à jour régulièrement et réalisée selon un processus entièrement automatisé.", "globalConstraint": { "maxScaleDenominator": 559082264.0287179, @@ -3489,7 +3489,7 @@ "ORTHOIMAGERY.ORTHOPHOTOS2006-2010$GEOPORTAIL:OGC:WMTS": { "name": "ORTHOIMAGERY.ORTHOPHOTOS2006-2010", - "title": "Photographies aériennes 2006-2010", + "title": "2006-2010", "description": "Prises de vues aériennes des territoires disponibles à la fin des années 2006 à 2010", "globalConstraint": { "maxScaleDenominator": 559082264.0287179, @@ -3616,7 +3616,7 @@ }, "ORTHOIMAGERY.ORTHOPHOTOS2000-2005$GEOPORTAIL:OGC:WMTS": { "name": "ORTHOIMAGERY.ORTHOPHOTOS2000-2005", - "title": "Photographies aériennes 2000-2005", + "title": "2000-2005", "description": "Prises de vues aériennes des territoires pour les années 2000 à 2005", "globalConstraint": { "maxScaleDenominator": 559082264.0287179, @@ -3743,7 +3743,7 @@ }, "ORTHOIMAGERY.ORTHOPHOTOS.1950-1965$GEOPORTAIL:OGC:WMTS": { "name": "ORTHOIMAGERY.ORTHOPHOTOS.1950-1965", - "title": "Photographies aériennes historiques 1950-1965", + "title": "1950-1965", "description": "Couverture en photographies aériennes de la France des années 50, telle qu'elle se présentait avant les grands aménagements des années 60. Cette couverture a été réalisée à partir des photographies aériennes historiques numérisées par l'IGN. Elle est disponible sur la France métropolitaine, les départements et régions d'Outre-Mer (la Guyane n'est que partiellement couverte) et les collectivités d'Outre-Mer sauf la Polynésie française. Les photographies sont orthorectifiées, c'est-à-dire corrigées des déformations dues à la prise de vue et au relief du terrain, et assemblées pour fournir une visualisation continue superposable avec le Référentiel à Grande Echelle (RGE®) ou les cartes.", "globalConstraint": { "maxScaleDenominator": 559082264.0287179, @@ -3901,7 +3901,7 @@ "GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN50.1950$GEOPORTAIL:OGC:WMTS": { "name": "GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN50.1950", - "title": "SCAN50 Historique de 1950", + "title": "1950 (Scan historique)", "description": "SCAN50 produit par l'IGN en 1950", "globalConstraint": { "maxScaleDenominator": 559082264.0287179, @@ -4028,7 +4028,7 @@ }, "GEOGRAPHICALGRIDSYSTEMS.ETATMAJOR40$GEOPORTAIL:OGC:WMTS": { "name": "GEOGRAPHICALGRIDSYSTEMS.ETATMAJOR40", - "title": "Carte de l'état-major (1820-1866)", + "title": "1820-1866 (Carte de l'état-major)", "description": "Carte française en couleurs du XIXè siècle en couleurs superposable aux cartes et données modernes.", "globalConstraint": { "maxScaleDenominator": 559082264.0287179, @@ -4137,7 +4137,7 @@ }, "GEOGRAPHICALGRIDSYSTEMS.CASSINI$GEOPORTAIL:OGC:WMTS": { "name": "GEOGRAPHICALGRIDSYSTEMS.CASSINI", - "title": "Carte de Cassini (XVIIIe siècle)", + "title": "XVIIIe siècle (Carte de Cassini)", "description": "Carte de Cassini en couleur (feuilles gravées et aquarellées), issue de l’exemplaire dit de « Marie-Antoinette » du XVIIIe siècle.", "globalConstraint": { "maxScaleDenominator": 559082264.0287179, diff --git a/src/js/dom.js b/src/js/dom.js index 38ecaf9e..3acb15db 100644 --- a/src/js/dom.js +++ b/src/js/dom.js @@ -15,6 +15,11 @@ const $backTopLeftBtn = document.getElementById("backTopLeftBtn"); const $compassBtn = document.getElementById("compassBtn"); const $layerManagerBtn = document.getElementById("layerManagerBtn"); const $sideBySideBtn = document.getElementById("sideBySideBtn"); +const $compareMode = document.getElementById("compareMode"); +const $sideBySideLeftLayer = document.getElementById("sideBySideLeftLayer"); +const $sideBySideRightLayer = document.getElementById("sideBySideRightLayer"); +const $compareLayers1Window = document.getElementById("compareLayers1Window"); +const $compareLayers2Window = document.getElementById("compareLayers2Window"); const $filterPoiBtn = document.getElementById("filterPoiBtn"); const $interactivityBtn = document.getElementById("interactivityBtn"); const $routeDrawBtns = document.getElementById("routeDrawBtns"); @@ -81,6 +86,11 @@ export default { $isochroneWindow, $positionWindow, $sideBySideBtn, + $compareMode, + $sideBySideLeftLayer, + $sideBySideRightLayer, + $compareLayers1Window, + $compareLayers2Window, $myaccountWindow, $informationsWindow, $informationsText, diff --git a/src/js/globals.js b/src/js/globals.js index 40714109..19bb2796 100644 --- a/src/js/globals.js +++ b/src/js/globals.js @@ -1,6 +1,7 @@ /** global: map */ let map = null; -let mapRLT = null; +let mapRLT1 = null; +let mapRLT2 = null; /** * global: layer display state @@ -54,6 +55,7 @@ let position = null; // Global Compare Plugin let compare = null; +let comparedLayers = ["ORTHOIMAGERY.ORTHOPHOTOS$GEOPORTAIL:OGC:WMTS", "ORTHOIMAGERY.ORTHOPHOTOS.1950-1965$GEOPORTAIL:OGC:WMTS"]; // Global Menu navigation let menu = null; @@ -81,7 +83,8 @@ let currentScroll = window.scrollY; export default { map, - mapRLT, + mapRLT1, + mapRLT2, layersDisplayed, backButtonState, mapState, @@ -102,6 +105,7 @@ export default { position, search, compare, + comparedLayers, menu, manager, poi, diff --git a/src/js/index.js b/src/js/index.js index 5c4d0b02..a3c39119 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -52,11 +52,10 @@ function app() { maxPitch: 0, touchPitch: false, }); - map.scrollZoom.setWheelZoomRate(1); - // Secondary map for RLT - const mapRLT = new maplibregl.Map({ - container: "mapRLT", + // Secondary maps for RLT + const mapRLT1 = new maplibregl.Map({ + container: "mapRLT1", zoom: 5, center: [2.0, 47.33], attributionControl: false, @@ -64,11 +63,28 @@ function app() { maxPitch: 0, touchPitch: false, }); - mapRLT.scrollZoom.setWheelZoomRate(1); + // disable map rotation using right click + drag + mapRLT1.dragRotate.disable(); + // disable map rotation using touch rotation gesture + mapRLT1.touchZoomRotate.disableRotation(); + const mapRLT2 = new maplibregl.Map({ + container: "mapRLT2", + zoom: 5, + center: [2.0, 47.33], + attributionControl: false, + locale: "fr", + maxPitch: 0, + touchPitch: false, + }); + // disable map rotation using right click + drag + mapRLT2.dragRotate.disable(); + // disable map rotation using touch rotation gesture + mapRLT2.touchZoomRotate.disableRotation(); // Enregistrement de la carte Globals.map = map; - Globals.mapRLT = mapRLT; + Globals.mapRLT1 = mapRLT1; + Globals.mapRLT2 = mapRLT2; // DEBUG window.mapGlobal = map; @@ -113,7 +129,8 @@ function app() { for (let layer in LayersConfig.rltLayerSources) { var source = LayersConfig.rltLayerSources[layer]; if (source.type !== "vector") { - mapRLT.addSource(layer, source); + mapRLT1.addSource(layer, source); + mapRLT2.addSource(layer, source); } } for (let layer in LayersConfig.thematicLayerSources) { diff --git a/src/js/layer-manager/layer-catalogue.js b/src/js/layer-manager/layer-catalogue.js index 74de86a7..4b16fcfc 100644 --- a/src/js/layer-manager/layer-catalogue.js +++ b/src/js/layer-manager/layer-catalogue.js @@ -87,22 +87,6 @@ class LayerCatalogue extends EventTarget { }); } - // TODO : only display them in RLT menu - - // var strRLTLayers = ""; - // var rltLayers = LayersConfig.getRLTLayers(); - // for(let j = 0; j < rltLayers.length; j++) { - // var props = LayersConfig.getLayerProps(rltLayers[j]); - // strRLTLayers += tplLayer({ - // type : "rltLayer", - // layerID : rltLayers[j], - // layerName : props.layer, - // layerQuickLook : LayersAdditional.getQuickLookUrl(props.layer), - // layerTitle : props.title, - // layerThematic : "" - // }); - // } - var strThematicButtons = ""; var thematicButtons = LayersConfig.getThematics(); for (let l = 0; l < thematicButtons.length; l++) { @@ -189,7 +173,7 @@ class LayerCatalogue extends EventTarget { // clic sur une couche de fonds document.querySelectorAll(".baseLayer").forEach((el) => { el.addEventListener('click', (e) => { - if (el.classList.contains("selectedLayer") || el.classList.contains("comparedLayer")) { + if (el.classList.contains("selectedLayer")) { this.removeLayer(el.id); } else { this.addLayer(el.id); @@ -199,7 +183,7 @@ class LayerCatalogue extends EventTarget { // clic sur une couche thematique document.querySelectorAll(".thematicLayer").forEach((el) => { el.addEventListener('click', (e) => { - if (el.classList.contains("selectedLayer") || el.classList.contains("comparedLayer")) { + if (el.classList.contains("selectedLayer")) { this.removeLayer(el.id); } else { this.addLayer(el.id); @@ -249,27 +233,24 @@ class LayerCatalogue extends EventTarget { if (!layerName) { return; } - if (Globals.mapState === "compare") { - this.#addCompareLayer(layerName); - } else { - var element = document.getElementById(layerName); - element.classList.add("selectedLayer"); - /** - * Evenement "addlayer" - * @event addlayer - * @type {*} - * @property {*} id - - */ - this.dispatchEvent( - new CustomEvent("addlayer", { - bubbles: true, - detail: { - id : layerName - } - }) - ); - } + var element = document.getElementById(layerName); + element.classList.add("selectedLayer"); + + /** + * Evenement "addlayer" + * @event addlayer + * @type {*} + * @property {*} id - + */ + this.dispatchEvent( + new CustomEvent("addlayer", { + bubbles: true, + detail: { + id : layerName + } + }) + ); } /** @@ -282,86 +263,25 @@ class LayerCatalogue extends EventTarget { if (!layerName) { return; } - if (Globals.mapState === "compare") { - this.#removeCompareLayer(layerName); - } else { - var element = document.getElementById(layerName); - element.classList.remove('selectedLayer'); - - /** - * Evenement "removelayer" - * @event removelayer - * @type {*} - * @property {*} id - - */ - this.dispatchEvent( - new CustomEvent("removelayer", { - bubbles: true, - detail: { - id : layerName - } - }) - ); - } - } - - /** - * Ajout d'une couche pour comparaison - * @param {*} layerName - */ - #addCompareLayer(layerName) { - // on supprime la couche précédemment ajoutée car sur l'outil de comparaison - // on est l'affichage d'une seule couche à la fois ! - document.querySelectorAll(".baseLayer").forEach(elem => { - if (elem.classList.contains('comparedLayer')) { - elem.classList.remove('comparedLayer'); - this.#removeCompareLayer(elem.id); - } - }); - document.getElementById(layerName).classList.add("comparedLayer"); - this.#setCompareLayerStyle(layerName); - } + var element = document.getElementById(layerName); + element.classList.remove('selectedLayer'); - /** - * Supprime la couche de comparaison - * @param {*} layerName - */ - #removeCompareLayer(layerName) { - document.querySelectorAll(".baseLayer").forEach(elem => { - elem.classList.remove('comparedLayer'); - }); - this.#setCompareLayerStyle(layerName); + /** + * Evenement "removelayer" + * @event removelayer + * @type {*} + * @property {*} id - + */ + this.dispatchEvent( + new CustomEvent("removelayer", { + bubbles: true, + detail: { + id : layerName + } + }) + ); } - /** - * Ajout du style pour une source donnée - * @param {*} source - nom de la source === nom de la couche - */ - #setCompareLayerStyle (source) { - let allLayersStyle = this.mapRLT.getStyle().layers; - var layerIndex = allLayersStyle.findIndex((l) => l.id === source); - var layerStyle = allLayersStyle[layerIndex] || null; - - if (source) { - if (layerIndex === -1) { - // le style n'existe pas, on ajoute donc le nouveau style de type raster - layerStyle = { - id : source, - source : source, - type : "raster" - }; - // HACK - // on positionne toujours le style avant ceux du calcul d'itineraires (directions) - // afin que le calcul soit toujours la couche visible du dessus ! - var layerIndexBefore = allLayersStyle.findIndex((l) => l.source === "maplibre-gl-directions"); - var layerIdBefore = (layerIndexBefore !== -1) ? allLayersStyle[layerIndexBefore].id : null; - this.mapRLT.addLayer(layerStyle, layerIdBefore); - } else { - // le style existe, on le supprime - this.mapRLT.removeLayer(source); - } - } - } } export default LayerCatalogue; diff --git a/src/js/layer-manager/layer-group.js b/src/js/layer-manager/layer-group.js index 76f7eede..820cf9c1 100644 --- a/src/js/layer-manager/layer-group.js +++ b/src/js/layer-manager/layer-group.js @@ -248,12 +248,13 @@ const addGray = (id) => { value = Globals.map.getPaintProperty(layer.id, `${layer.type}-color`); if (value) { originalLayerColors[layer.id][`${layer.type}-color`] = value; - if (value.stops) { - var greyStops = []; - value.stops.forEach((val) => { - greyStops.push([val[0], convert(val[1])]); - }); - Globals.map.setPaintProperty(layer.id, `${layer.type}-color`, {stops: greyStops}) + if (value[0] == "step") { + var greyStep = ["step"]; + for (let i = 2; i < greyStep.length; i+= 2) { + greyStep.push(value[i - 1]); + greyStep.push(convert(value[i])); + } + Globals.map.setPaintProperty(layer.id, `${layer.type}-color`, greyStep) } else { Globals.map.setPaintProperty(layer.id, `${layer.type}-color`, convert(value)); } diff --git a/src/js/map-buttons-listeners.js b/src/js/map-buttons-listeners.js index 690fe468..8dd8875c 100644 --- a/src/js/map-buttons-listeners.js +++ b/src/js/map-buttons-listeners.js @@ -42,7 +42,7 @@ const addListeners = () => { }); // Bouton Comparaison de carte - DOM.$sideBySideBtn.addEventListener("click", () => { Globals.compare.toggle(); }); + DOM.$sideBySideBtn.addEventListener("click", () => { Globals.menu.open("compare"); }); // Bouton du gestionnaire de couches DOM.$layerManagerBtn.addEventListener("click", () => { Globals.menu.open("layerManager"); }); diff --git a/src/js/map-interactivity/interactivity-indicator.js b/src/js/map-interactivity/interactivity-indicator.js index acfbb98c..4b65839d 100644 --- a/src/js/map-interactivity/interactivity-indicator.js +++ b/src/js/map-interactivity/interactivity-indicator.js @@ -56,7 +56,7 @@ class InteractivityIndicator { if (this.hardDisabled) { return; } - if (this.pii && this.position && Math.round(e.target.getZoom()) > this.piiMinZoom) { + if (this.pii && this.position && Math.floor(e.target.getZoom()) >= this.piiMinZoom) { this.active(); } else { this.dontClear = true; @@ -79,7 +79,7 @@ class InteractivityIndicator { if (layer[0] === this.id) { this.pii = true; this.position = true; - if (Math.round(this.map.getZoom()) > this.piiMinZoom) { + if (Math.floor(this.map.getZoom()) >= this.piiMinZoom) { this.active(); } else { this.disable(); diff --git a/src/js/nav.js b/src/js/nav.js index dff3f024..5f449d83 100644 --- a/src/js/nav.js +++ b/src/js/nav.js @@ -38,7 +38,6 @@ class MenuNavigation { }); // "Où suis-je ?" document.getElementById("position").addEventListener("click", () => { - Globals.compare.hide(); Globals.position.compute() .then(() => { this.open("position"); @@ -46,17 +45,14 @@ class MenuNavigation { }); // "A proximité" document.getElementById("isochrone").addEventListener("click", () => { - Globals.compare.hide(); this.open("isochrone"); }); // "S'y rendre" document.getElementById("directions").addEventListener("click", () => { - Globals.compare.hide(); this.open("directions"); }); // "Tracer un itinéraire" document.getElementById("routeDraw").addEventListener("click", () => { - Globals.compare.hide(); this.open("routeDraw"); }); // "Compte" @@ -109,6 +105,38 @@ class MenuNavigation { // y'a t il des particularités sur l'ouverture du panneau demandé ? var isSpecific = false; switch (id) { + case "compareLayers1": + DOM.$tabContainer.style.removeProperty("top"); + DOM.$bottomButtons.style.removeProperty("bottom"); + DOM.$compareLayers2Window.classList.add("d-none"); + DOM.$compareLayers1Window.classList.remove("d-none"); + DOM.$sideBySideLeftLayer.classList.add("d-none"); + Globals.currentScrollIndex = 2; + break; + case "compareLayers2": + DOM.$tabContainer.style.removeProperty("top"); + DOM.$bottomButtons.style.removeProperty("bottom"); + DOM.$compareLayers1Window.classList.add("d-none"); + DOM.$compareLayers2Window.classList.remove("d-none"); + DOM.$sideBySideRightLayer.classList.add("d-none"); + Globals.currentScrollIndex = 2; + break; + case "compare": + DOM.$search.style.display = "none"; + DOM.$filterPoiBtn.classList.add('d-none'); + DOM.$sideBySideBtn.classList.add('d-none'); + DOM.$geolocateBtn.classList.add('d-none'); + DOM.$layerManagerBtn.classList.add('d-none'); + DOM.$backTopLeftBtn.classList.remove('d-none'); + DOM.$compareMode.classList.remove('d-none'); + DOM.$sideBySideLeftLayer.classList.remove('d-none'); + DOM.$sideBySideRightLayer.classList.remove('d-none'); + DOM.$tabContainer.style.top = "100vh"; + DOM.$bottomButtons.style.bottom = "calc(42px + env(safe-area-inset-bottom))"; + Globals.compare.show(); + Globals.interactivityIndicator.hardDisable(); + Globals.currentScrollIndex = 0; + break; case "routeDraw": DOM.$search.style.display = "none"; DOM.$filterPoiBtn.style.top = "calc(10px + env(safe-area-inset-top))"; @@ -116,12 +144,11 @@ class MenuNavigation { DOM.$routeDrawBtns.classList.remove('d-none'); DOM.$routeDrawEdit.classList.remove('d-none'); if (!window.matchMedia("(min-width: 615px), screen and (min-aspect-ratio: 1/1) and (min-width:400px)").matches) { - DOM.$bottomButtons.style.bottom = "calc(220px + env(safe-area-inset-bottom))"; + DOM.$bottom.style.bottom = "calc(220px + env(safe-area-inset-bottom))"; } else { DOM.$bottomButtons.style.left = "calc(100vh + env(safe-area-inset-left) + 42px)"; DOM.$bottomButtons.style.width = "auto"; } - DOM.$tabContainer.style.backgroundColor = "white"; DOM.$sideBySideBtn.classList.add('d-none'); Globals.interactivityIndicator.hardDisable(); @@ -249,6 +276,39 @@ class MenuNavigation { var isSpecific = false; var isFinished = false; // hack pour search ! switch (id) { + case "compareLayers1": + DOM.$tabContainer.style.top = "100vh"; + DOM.$bottomButtons.style.bottom = "calc(42px + env(safe-area-inset-bottom))"; + DOM.$compareLayers1Window.classList.add("d-none"); + DOM.$sideBySideLeftLayer.classList.remove("d-none"); + Globals.currentScrollIndex = 0; + isSpecific = true; + isFinished = true; + break; + case "compareLayers2": + DOM.$tabContainer.style.top = "100vh"; + DOM.$bottomButtons.style.bottom = "calc(42px + env(safe-area-inset-bottom))"; + DOM.$compareLayers2Window.classList.add("d-none"); + DOM.$sideBySideRightLayer.classList.remove("d-none"); + Globals.currentScrollIndex = 0; + isSpecific = true; + isFinished = true; + break; + case "compare": + DOM.$search.style.display = "flex"; + DOM.$filterPoiBtn.classList.remove('d-none'); + DOM.$sideBySideBtn.classList.remove('d-none'); + DOM.$geolocateBtn.classList.remove('d-none'); + DOM.$layerManagerBtn.classList.remove('d-none'); + DOM.$backTopLeftBtn.classList.add('d-none'); + DOM.$compareMode.classList.add('d-none'); + DOM.$sideBySideLeftLayer.classList.add('d-none'); + DOM.$sideBySideRightLayer.classList.add('d-none'); + DOM.$tabContainer.style.removeProperty("top"); + DOM.$bottomButtons.style.removeProperty("bottom"); + Globals.compare.hide(); + Globals.interactivityIndicator.enable(); + break; case "routeDraw": DOM.$search.style.display = "flex"; DOM.$filterPoiBtn.style.removeProperty("top"); @@ -393,6 +453,10 @@ class MenuNavigation { * @param {*} id */ #close(id) { + if (["compareLayers1", "compareLayers2"].includes(id)) { + Globals.backButtonState = 'compare'; // on revient sur le contrôle ! + return; + } Globals.controller.abort(); Globals.controller = new AbortController(); Globals.signal = Globals.controller.signal; @@ -456,7 +520,9 @@ class MenuNavigation { /** ... */ #scrollTo(value) { - DOM.$tabContainer.style.removeProperty("top"); + if (Globals.backButtonState !== "compare") { + DOM.$tabContainer.style.removeProperty("top"); + } if (window.matchMedia("(min-width: 615px), screen and (min-aspect-ratio: 1/1) and (min-width:400px)").matches) { if (Globals.currentScrollIndex == 0) { return diff --git a/src/js/route-draw/route-draw.js b/src/js/route-draw/route-draw.js index 3b3557de..bcc3642b 100644 --- a/src/js/route-draw/route-draw.js +++ b/src/js/route-draw/route-draw.js @@ -32,7 +32,7 @@ class RouteDraw { this.configuration = this.options.configuration || { linesource: "route-draw-line", pointsource: "route-draw-point", - api: "https://data.geopf.fr/navigation/itineraire?resource=bdtopo-osrm&getSteps=false&timeUnit=second&", + api: "https://data.geopf.fr/navigation/itineraire?resource=bdtopo-osrm&getSteps=false&timeUnit=second&optimization=shortest", template: (values) => { return `start=${values.start.lng},${values.start.lat}&end=${values.end.lng},${values.end.lat}&profile=${values.profile}` } diff --git a/src/js/state.js b/src/js/state.js index df8335d7..3d43670d 100644 --- a/src/js/state.js +++ b/src/js/state.js @@ -53,6 +53,15 @@ const onBackKeyDown = () => { if (Globals.backButtonState === 'poi') { Globals.menu.close('poi'); } + if (Globals.backButtonState === 'compare') { + Globals.menu.close('compare'); + } + if (Globals.backButtonState === 'compareLayers1') { + Globals.menu.close('compareLayers1'); + } + if (Globals.backButtonState === 'compareLayers2') { + Globals.menu.close('compareLayers2'); + } if (Globals.backButtonState === 'routeDraw') { Globals.menu.close('routeDraw'); }