diff --git a/.github/workflows/android-deploy.yml b/.github/workflows/android-deploy.yml index af052c3f..965971aa 100644 --- a/.github/workflows/android-deploy.yml +++ b/.github/workflows/android-deploy.yml @@ -21,6 +21,7 @@ jobs: echo "GPF_key=${{ secrets.GPF_key }}" > .env echo "signalement_url=${{ secrets.SIGNALEMENT_URL }}" >> .env echo "osm_bearer_token=${{ secrets.OSM_BEARER_TOKEN }}" >> .env + echo "geovelo_key=${{ secrets.GEOVELO_KEY }}" >> .env - name: Setup Node.js uses: actions/setup-node@v4 diff --git a/.github/workflows/ios-deploy.yml b/.github/workflows/ios-deploy.yml index b0a32dfb..c3adc723 100644 --- a/.github/workflows/ios-deploy.yml +++ b/.github/workflows/ios-deploy.yml @@ -21,6 +21,7 @@ jobs: echo "GPF_key=${{ secrets.GPF_key }}" > .env echo "signalement_url=${{ secrets.SIGNALEMENT_URL }}" >> .env echo "osm_bearer_token=${{ secrets.OSM_BEARER_TOKEN }}" >> .env + echo "geovelo_key=${{ secrets.GEOVELO_KEY }}" >> .env - name: Setup Node.js uses: actions/setup-node@v4 diff --git a/src/css/assets/directions/details-o.svg b/src/css/assets/directions/details-o.svg new file mode 100644 index 00000000..0aba7599 --- /dev/null +++ b/src/css/assets/directions/details-o.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/css/assets/directions/details.svg b/src/css/assets/directions/details.svg new file mode 100644 index 00000000..e01c5e96 --- /dev/null +++ b/src/css/assets/directions/details.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/css/assets/directions/invisible.svg b/src/css/assets/directions/invisible.svg deleted file mode 100644 index d4286c09..00000000 --- a/src/css/assets/directions/invisible.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/css/assets/directions/link-play.svg b/src/css/assets/directions/link-play.svg new file mode 100644 index 00000000..0e9841e0 --- /dev/null +++ b/src/css/assets/directions/link-play.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/css/assets/directions/location-step-add.svg b/src/css/assets/directions/location-step-add.svg index 5126c872..55ef1998 100644 --- a/src/css/assets/directions/location-step-add.svg +++ b/src/css/assets/directions/location-step-add.svg @@ -1,6 +1,6 @@ - + diff --git a/src/css/assets/directions/velo-s.svg b/src/css/assets/directions/velo-s.svg new file mode 100644 index 00000000..a1286cb4 --- /dev/null +++ b/src/css/assets/directions/velo-s.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/css/assets/directions/velo.svg b/src/css/assets/directions/velo.svg new file mode 100644 index 00000000..110ab850 --- /dev/null +++ b/src/css/assets/directions/velo.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/css/assets/directions/visible.svg b/src/css/assets/directions/visible.svg deleted file mode 100644 index 80aa421b..00000000 --- a/src/css/assets/directions/visible.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/css/assets/edit-white.svg b/src/css/assets/edit-green.svg similarity index 79% rename from src/css/assets/edit-white.svg rename to src/css/assets/edit-green.svg index 5a295415..80cb8cc6 100644 --- a/src/css/assets/edit-white.svg +++ b/src/css/assets/edit-green.svg @@ -1,6 +1,6 @@ - diff --git a/src/css/assets/isochrone-white.svg b/src/css/assets/isochrone-white.svg index bc85423c..00d50dd9 100644 --- a/src/css/assets/isochrone-white.svg +++ b/src/css/assets/isochrone-white.svg @@ -6,4 +6,4 @@ - \ No newline at end of file + diff --git a/src/css/directions-results.css b/src/css/directions-results.css index 99e36f42..3754bbdc 100644 --- a/src/css/directions-results.css +++ b/src/css/directions-results.css @@ -65,16 +65,22 @@ background-image: url("assets/directions/voiture.svg"); } +#directionsSummaryTransportVelo { + background-image: url("assets/directions/velo.svg"); +} + .lblDirectionsSummaryTransport { width: 30px; height: 30px; display: inline-block; background-repeat: no-repeat; background-position: left; + flex-shrink: 0; } #directionsSummaryComputation { - font-size: 12px; + color: var(--mid-grey); + font-family: "Open Sans Semibold"; } .lblDirectionsSummaryComputation { @@ -104,14 +110,14 @@ cursor: pointer; text-align: right; width: 75px; - background-image: url("assets/directions/invisible.svg"); + background-image: url("assets/directions/details.svg"); background-repeat: no-repeat; - background-position: 8px; + background-position: 15px; color: var(--dark-green); } #directionsDetails input[id="directionsShowDetail"]:checked + label { - background-image: url("assets/directions/visible.svg"); + background-image: url("assets/directions/details-o.svg"); background-color: var(--dark-green); color: white; } @@ -233,7 +239,12 @@ font-family: "Fira Sans Semibold"; } - +.divPositionAdressOriginInfo.geovelolink { + text-decoration: none; + background-image: url(assets/directions/link-play.svg); + background-size: 16px; + background-position: center right 16px; +} @media screen and (min-aspect-ratio: 1/1) and (min-width:400px) { #directionsListDetails { diff --git a/src/css/directions.css b/src/css/directions.css index 31884a68..ab7852b9 100644 --- a/src/css/directions.css +++ b/src/css/directions.css @@ -43,7 +43,7 @@ z-index: 2; } -.divDirectionsTransport, .divDirectionsComputation { +.divDirectionsComputation { display: flex; position: relative; justify-content: space-between; @@ -59,7 +59,20 @@ align-items: center; } -.lblDirectionsTransport, .lblDirectionsComputation { +.divDirectionsTransport { + display: flex; + position: relative; + justify-content: space-around; + margin: auto; + height: calc(50px + 1rem); + width: calc(100% - 46px); + padding: 8px; + border-radius: 100px; + margin: 0 15px 10px 15px; + align-items: center; +} + +.lblDirectionsComputation { color: var(--mid-grey); display: flex; flex-direction: row-reverse; @@ -76,9 +89,37 @@ background-position: 12px 3px; font-family: "Open Sans Semibold"; font-size: 14px; + flex-shrink: 0; } -.divDirectionsTransport input[type="radio"]:checked + label, .divDirectionsComputation input[type="radio"]:checked + label { +.lblDirectionsTransport { + display: flex; + flex-direction: column-reverse; + align-items: center; + margin: 0; + justify-content: space-around; +} + +.lblDirectionsTransport span { + display: inline-block; + width: 44px; + height: 44px; + background-repeat: no-repeat; + background-position: center; + border-radius: 100%; + background-color: var(--light-grey); + margin-bottom: 6px; +} + +input:checked + .lblDirectionsTransport span { + background-color: var(--dark-green); +} + +.divDirectionsTransport input[type="radio"]:checked + label { + color: var(--darker-green); +} + +.divDirectionsComputation input[type="radio"]:checked + label { color: white; } @@ -92,6 +133,10 @@ transform: translateX(-5px); } +.divDirectionsTransport input[id="directionsTransportVelo"]:checked ~ .sliderDirections { + transform: translateX(calc(200% - 15px)); +} + .sliderDirections, .sliderComputation { position: absolute; display: flex; @@ -105,11 +150,6 @@ #directionsTransportVoiture + label > span { background-image: url("assets/directions/voiture.svg"); - display: inline-block; - width: 25px; - height: 100%; - background-repeat: no-repeat; - background-position: 0px center; } #directionsTransportVoiture:checked + label > span { @@ -118,17 +158,35 @@ #directionsTransportPieton + label > span { background-image: url("assets/directions/pieton.svg"); - display: inline-block; - width: 25px; - height: 100%; - background-repeat: no-repeat; - background-position: 0px center; } #directionsTransportPieton:checked + label > span { background-image: url("assets/directions/pieton-s.svg"); } +#directionsTransportVelo + label > span { + background-image: url("assets/directions/velo.svg"); +} + +#directionsTransportVelo:checked + label > span { + background-image: url("assets/directions/velo-s.svg"); +} + +.divDirectionsTransport:has(#directionsTransportVelo:checked) ~ .divDirectionsComputation { + display: none; +} + +.divDirectionsBikeForm { + display: none; + justify-content: center; + gap: 10px; + font-size: 15px; +} + +.divDirectionsTransport:has(#directionsTransportVelo:checked) ~ .divDirectionsBikeForm { + display: flex; +} + /* * locations */ @@ -265,24 +323,28 @@ display: flex; margin: auto; padding: 10px; - font-family: "Open Sans"; + font-family: "Open Sans Semibold"; max-height: 60px; transition: max-height .2s ease-out; + width: fit-content; + justify-content: center; } #directionsLocationImg_step { display: flex; - width: 180px; + width: calc(17rem - 40px); + max-width: calc(100% - 56px); height: 40px; padding-left: 40px; align-items: center; background-image: url("assets/directions/location-step-add.svg"); line-height: 40px; background-position-y: 9px; - color: var(--dark-grey); background-color: #fff0; transition: background-color 0.1s; border-radius: 8px; + color: var(--mid-grey); + transform: translateX(20px); } #directionsLocationImg_step.animated { diff --git a/src/css/layer-manager.css b/src/css/layer-manager.css index 0a799677..6bf00a18 100644 --- a/src/css/layer-manager.css +++ b/src/css/layer-manager.css @@ -39,7 +39,7 @@ justify-content: space-between; align-items: center; border-bottom: 2px solid var(--grey-2); - font-family: "Fira Sans SemiBold"; + font-family: "Fira Sans Semibold"; font-size: 15px; position: sticky; top: calc(39px + var(--safe-area-inset-top)); diff --git a/src/css/my-account.css b/src/css/my-account.css index a120a978..e2852555 100644 --- a/src/css/my-account.css +++ b/src/css/my-account.css @@ -185,7 +185,7 @@ align-items: center; padding-bottom: 6px; border-bottom: 2px solid var(--grey-2); - font-family: "Fira Sans SemiBold"; + font-family: "Fira Sans Semibold"; font-size: 15px; white-space: nowrap; flex-shrink: 0; diff --git a/src/css/position.css b/src/css/position.css index a003a839..fd963052 100644 --- a/src/css/position.css +++ b/src/css/position.css @@ -219,15 +219,15 @@ display: flex; align-items: center; padding: 10px 14px; - color: white; - background-color: var(--dark-green); + color: var(--dark-green); + background-color: var(--false-white); + border: var(--dark-green) 1px solid; border-radius: 50px; margin-right: 12px; cursor: pointer; position: relative; transition: all 0.3s ease-in-out; outline: none; - border: none; white-space: nowrap; font-family: "Open Sans Semibold"; font-size: 12px; @@ -263,6 +263,11 @@ background-color: var(--event-main); } +#positionRoute { + color: white; + background-color: var(--dark-green); +} + /* * coordonnées */ diff --git a/src/js/directions/directions-dom.js b/src/js/directions/directions-dom.js index 485e42ad..92e908f4 100644 --- a/src/js/directions/directions-dom.js +++ b/src/js/directions/directions-dom.js @@ -21,6 +21,7 @@ let DirectionsDOM = { inputDeparture: null, inputArrival: null, buttonCompute: null, + electricBike: null, }, /** @@ -37,6 +38,8 @@ let DirectionsDOM = { container.appendChild(this.__addComputeContainerLocationsDOMElement()); // ajout du mode de calcul container.appendChild(this.__addComputeContainerComputationDOMElement()); + // ajout du formulaire vélo + container.appendChild(this.__addComputeContainerBikeFormDOMElement()); // ajout du bouton submit container.appendChild(this.__addComputeButtonDOMElement()); return container; @@ -75,6 +78,12 @@ let DirectionsDOM = { transport = self.dom.inputPedestrian.value; } } + // vélo ? + if (self.dom.inputBicycle) { + if (self.dom.inputBicycle.checked) { + transport = self.dom.inputBicycle.value; + } + } var computation = null; // fast ? @@ -90,6 +99,13 @@ let DirectionsDOM = { } } + var electricBike = false; + if (self.dom.electricBike) { + if (self.dom.electricBike.checked) { + electricBike = true; + } + } + // recuperation des coordonnées issues du geocodage // le geocodage enregistre les coordonnées dans la tag data-coordinates : // data-coordinates = "[2.24,48.80]" @@ -120,7 +136,8 @@ let DirectionsDOM = { self.compute({ transport: transport, computation: computation, - locations: locations + locations: locations, + electricBike: electricBike, }); return false; @@ -225,10 +242,26 @@ let DirectionsDOM = { labelCar.title = "Véhicule"; div.appendChild(labelCar); - var slider = document.createElement("span"); - slider.className = "sliderDirections"; - div.appendChild(slider); - + var inputBicycle = this.dom.inputBicycle = document.createElement("input"); + inputBicycle.id = "directionsTransportVelo"; + inputBicycle.type = "radio"; + inputBicycle.name = "Transport"; + inputBicycle.value = "Velo"; + inputBicycle.addEventListener("change", function (e) { + if (e.target.checked) { + self.obj.configuration.profile = "bicycle"; + } + }); + div.appendChild(inputBicycle); + + var labelBicycle = document.createElement("label"); + var spanBicycle = document.createElement("span"); + labelBicycle.textContent = "À vélo"; + labelBicycle.appendChild(spanBicycle); + labelBicycle.className = "lblDirectionsTransport"; + labelBicycle.htmlFor = "directionsTransportVelo"; + labelBicycle.title = "À vélo"; + div.appendChild(labelBicycle); return div; }, @@ -237,6 +270,32 @@ let DirectionsDOM = { * @returns {DOMElement} * @private */ + __addComputeContainerBikeFormDOMElement() { + var div = document.createElement("div"); + div.className = "divDirectionsBikeForm"; + var labelElectric = document.createElement("label"); + labelElectric.classList.add("toggleSwitch"); + var electricInput = this.dom.electricBike = document.createElement("input"); + electricInput.classList.add("toggleInput"); + electricInput.type = "checkbox"; + var electricSpan = document.createElement("span"); + electricSpan.classList.add("toggleSlider"); + labelElectric.appendChild(electricInput); + labelElectric.appendChild(electricSpan); + div.appendChild(labelElectric); + + var textSpan = document.createElement("span"); + textSpan.innerText = "Vélo à assistance électrique ?"; + div.appendChild(textSpan); + + return div; + }, + + /** + * ajoute le container sur les options vélo + * @returns {DOMElement} + * @private + */ __addComputeContainerComputationDOMElement() { // https://uiverse.io/Yaya12085/rude-mouse-79 var div = document.createElement("div"); diff --git a/src/js/directions/directions-results-dom.js b/src/js/directions/directions-results-dom.js index 333a6c6d..48b2456e 100644 --- a/src/js/directions/directions-results-dom.js +++ b/src/js/directions/directions-results-dom.js @@ -41,18 +41,32 @@ let DirectionsResultsDOM = { data.distance, data.duration, data.transport, - data.computation + data.computation, )); // ajout du bouton détails noDetailsDiv.appendChild(this.__addResultsDetailsContainerDOMElement()); container.appendChild(noDetailsDiv); // ajout des détails try { - container.appendChild(this.__addResultsListDetailsContainerDOMElement(data.instructions, data.transport)); } catch (err) { console.error(err); } + // Ajout du lien Géovélo le cas échéant + if (data.transport === "Velo") { + var linkGeovelo = document.createElement("a"); + linkGeovelo.classList.add("divPositionAdressOriginInfo", "geovelolink"); + const start = data.waypoints.shift(); + const end = data.waypoints.pop(); + linkGeovelo.href = `https://www.geovelo.app/route?from=${start[0]},${start[1]}&to=${end[0]},${end[1]}`; + if (data.waypoints.length > 0) { + data.waypoints = data.waypoints.map( point => `${point[0]},${point[1]}`); + linkGeovelo.href += `&steps=${data.waypoints.join(";")}`; + } + linkGeovelo.target = "_blank"; + linkGeovelo.textContent = "Lancer la navigation et plus, sur Géovélo"; + container.appendChild(linkGeovelo); + } return container; }, @@ -109,7 +123,6 @@ let DirectionsResultsDOM = { labelComputation.className = "lblDirectionsSummaryComputation"; labelComputation.textContent = computation; line2.appendChild(labelComputation); - div.appendChild(line1); div.appendChild(line2); diff --git a/src/js/directions/directions.js b/src/js/directions/directions.js index e76a689b..c01537ad 100644 --- a/src/js/directions/directions.js +++ b/src/js/directions/directions.js @@ -4,7 +4,7 @@ * This program and the accompanying materials are made available under the terms of the GPL License, Version 3.0. */ -import { decode } from "@placemarkio/polyline"; +import { decode, encode } from "@placemarkio/polyline"; import MapLibreGlDirections from "@maplibre/maplibre-gl-directions"; import maplibregl from "maplibre-gl"; import DirectionsDOM from "./directions-dom"; @@ -77,7 +77,7 @@ class Directions { layers: DirectionsLayers.layers, dragThreshold: 10, refreshOnMove: false, - bearings: false + bearings: false, }; // paramètres du calcul @@ -97,10 +97,47 @@ class Directions { let url; let method = "get"; let payload = ""; - if (configuration.profile == "pedestrian") { + let headers = {}; + let body = ""; + this.configuration.requestOptions.geometries = "polyline5"; + if (configuration.profile === "pedestrian") { configuration.optimization = "shortest"; } - url = `${configuration.api}?resource=bdtopo-valhalla&profile=${configuration.profile}&optimization=${configuration.optimization}&start=${waypointsCoordinates.shift()}&end=${waypointsCoordinates.pop()}&intermediates=${waypointsCoordinates.join("|")}&geometryFormat=polyline`; + // API Géovélo + if (configuration.profile === "bicycle") { + this.configuration.requestOptions.geometries = "polyline6"; + method = "post"; + url = "https://backend.geovelo.fr/api/v2/computedroutes?geometry=true&single_result=true&bike_stations=false"; + const bikeDetails = {}; + if (this.electricBike) { + bikeDetails.eBike = true; + } + headers["Content-Type"] = "application/json"; + headers["Api-Key"] = process.env.geovelo_key; + let waypointIdx = 0; + const waypoints = waypointsCoordinates.map((coords) => { + let title = `Point intermédiaire ${waypointIdx}`; + if (waypointIdx === 0) { + title = "Départ"; + } + if (waypointIdx === waypointsCoordinates.length - 1) { + title = "Arrivée"; + } + waypointIdx++; + return { + title: title, + latitude: coords[1], + longitude: coords[0], + }; + }); + body = JSON.stringify({ + waypoints: waypoints, + bikeDetails: bikeDetails, + }); + // API GPF + } else { + url = `${configuration.api}?resource=bdtopo-valhalla&profile=${configuration.profile}&optimization=${configuration.optimization}&start=${waypointsCoordinates.shift()}&end=${waypointsCoordinates.pop()}&intermediates=${waypointsCoordinates.join("|")}&geometryFormat=polyline`; + } if (waypointsBearings) { console.debug(waypointsBearings); @@ -109,16 +146,19 @@ class Directions { return { method, url, - payload + payload, + headers, + body, }; }; - const self = this; - // REMOVEME: override buildRequest method - this.obj.fetch = async function({ method, url, payload }) { + this.obj.fetch = async function({ method, url, payload, headers, body }) { + if (payload) { + console.warn(payload); + } const response = (await (method === "get" ? await fetch(`${url}`, { signal: this.abortController?.signal }) - : console.debug(payload) + : await fetch(`${url}`, { signal: this.abortController?.signal, method: method, headers: headers, body: body }) ).json()); const formatedResponse = { @@ -127,63 +167,92 @@ class Directions { waypoints: [], }; - const route = { - geometry: response.geometry, - legs: [], - weight_name: "routability", - weight: this.configuration.optimization === "fastest" ? response.duration : response.distance, - duration: response.duration, - distance: response.distance, - }; - const pointFields = Array.from(self.dom.container.querySelectorAll(".inputDirectionsLocations")).filter(input => input.value.trim() !== ""); - - for (let i = 0; i < response.portions.length; i++) { - const portion = response.portions[i]; - if (formatedResponse.waypoints.length === 0) { + // API GPF + if (response.geometry) { + const route = { + geometry: response.geometry, + legs: [], + weight_name: "routability", + weight: this.configuration.optimization === "fastest" ? response.duration : response.distance, + duration: response.duration, + distance: response.distance, + }; + const pointFields = Array.from(self.dom.container.querySelectorAll(".inputDirectionsLocations")).filter(input => input.value.trim() !== ""); + + for (let i = 0; i < response.portions.length; i++) { + const portion = response.portions[i]; + if (formatedResponse.waypoints.length === 0) { + formatedResponse.waypoints.push({ + hint: "-1", + name: pointFields[0].value, + location: [parseFloat(portion.start.split(",")[0]), parseFloat(portion.start.split(",")[1])], + }); + } formatedResponse.waypoints.push({ - hint: "-1", - name: pointFields[0].value, - location: [parseFloat(portion.start.split(",")[0]), parseFloat(portion.start.split(",")[1])], + hint: "" + i, + name: pointFields[i + 1].value, + location: [parseFloat(portion.end.split(",")[0]), parseFloat(portion.end.split(",")[1])], }); - } - formatedResponse.waypoints.push({ - hint: "" + i, - name: pointFields[i + 1].value, - location: [parseFloat(portion.end.split(",")[0]), parseFloat(portion.end.split(",")[1])], - }); - route.legs.push({ - steps: [], - summary: "" + i, - weight: this.configuration.optimization === "fastest" ? portion.duration : portion.distance, - duration: portion.duration, - distance: portion.distance, - }); - for (let j = 0; j < portion.steps.length; j++) { - const step = portion.steps[j]; - route.legs[i].steps.push({ - geometry: step.geometry, - maneuver: { - bearing_after: 0, - bearing_before: 0, - location: [0, 0], - modifier: step.instruction.modifier, - type: step.instruction.type, - }, - mode: this.configuration.profile, - driving_side: "right", - name: step.attributes.name.nom_1_droite, - intersections: [], - weight: this.configuration.optimization === "fastest" ? step.duration : step.distance, - duration: step.duration, - distance: step.distance, + route.legs.push({ + steps: [], + summary: "" + i, + weight: this.configuration.optimization === "fastest" ? portion.duration : portion.distance, + duration: portion.duration, + distance: portion.distance, }); + for (let j = 0; j < portion.steps.length; j++) { + const step = portion.steps[j]; + route.legs[i].steps.push({ + geometry: step.geometry, + maneuver: { + bearing_after: 0, + bearing_before: 0, + location: [0, 0], + modifier: step.instruction.modifier, + type: step.instruction.type, + }, + mode: this.configuration.profile, + driving_side: "right", + name: step.attributes.name.nom_1_droite, + intersections: [], + weight: this.configuration.optimization === "fastest" ? step.duration : step.distance, + duration: step.duration, + distance: step.distance, + }); + } } + formatedResponse.routes.push(route); + // API Geovelo + } else if (response[0].sections) { + const routeCoords = decode(response[0].sections[0].geometry, 6); + + const newGeom = encode([ + [response[0].waypoints[0].longitude, response[0].waypoints[0].latitude], + ...routeCoords, + [response[0].waypoints.slice(-1)[0].longitude, response[0].waypoints.slice(-1)[0].latitude], + ], 6); + + const route = { + geometry: newGeom, + legs: [{ steps: [] }], + weight_name: "routability", + weight: this.configuration.optimization === "fastest" ? response.duration : response.distance, + duration: response[0].duration, + distance: response[0].distances.total, + }; + response[0].waypoints.forEach( (waypoint) => { + formatedResponse.waypoints.push({ + hint: waypoint.title, + name: waypoint.title, + location: [waypoint.longitude, waypoint.latitude], + }); + }); + + formatedResponse.routes.push(route); } - formatedResponse.routes.push(route); return formatedResponse; }; - // END REMOVEME // INFO sans interaction par défaut ! // > choix d'activer via la méthode publique... @@ -199,9 +268,6 @@ class Directions { this.#addPreviewSourcesAndLayers(); this.previewPoints = []; - // fonction d'event avec bind - this.handleAddWayPoint = this.#onAddWayPoint.bind(this); - // event interactif this.#listeners(); } @@ -260,6 +326,9 @@ class Directions { case "Voiture": this.configuration.profile = "car"; break; + case "Velo": + this.configuration.profile = "bicycle"; + break; default: break; } @@ -280,11 +349,15 @@ class Directions { default: break; } + if (settings.transport === "Velo") { + message = "Itinéraire calculé via Géovélo."; + } settings.computation = { code : code, message : message }; } + this.obj.electricBike = settings.electricBike; this.settings = settings; if (settings.locations && settings.locations.length) { try { @@ -295,9 +368,9 @@ class Directions { if (settings.locations[index]) { point = JSON.parse(settings.locations[index]); points.push(point); - this.obj.addWaypoint(point); } } + this.obj.waypoints = points; } catch (e) { // catching des exceptions JSON console.error(e); @@ -310,7 +383,6 @@ class Directions { * ajout d'ecouteurs pour la saisie interactive */ #listeners() { - this.obj.on("addwaypoint", this.handleAddWayPoint); // events this.obj.on("fetchroutesstart", () => { this.__setComputeButtonLoading(); @@ -331,19 +403,27 @@ class Directions { // } if (e.data.code === "Ok") { this.#removePreview(); - this.results = new DirectionsResults(this.map, null, { - duration : e.data.routes[0].duration || "", - distance : e.data.routes[0].distance || "", - transport : this.settings.transport, - computation : this.settings.computation.message, - instructions : e.data.routes[0].legs, - geometry : e.data.routes[0].geometry, - waypoints : e.data.waypoints, - elevation : this.elevation, - }); + try { + this.results = new DirectionsResults(this.map, null, { + duration : e.data.routes[0].duration || "", + distance : e.data.routes[0].distance || "", + transport : this.settings.transport, + computation : this.settings.computation.message, + instructions : e.data.routes[0].legs, + geometry : e.data.routes[0].geometry, + waypoints : e.data.waypoints, + elevation : this.elevation, + }); + } catch (error) { + console.error(error); + } this.results.show(); let routeCoordinates = []; - decode(e.data.routes[0].geometry).forEach( (lnglat) => { + let precision = 5; + if (this.settings.transport === "Velo") { + precision = 6; + } + decode(e.data.routes[0].geometry, precision).forEach( (lnglat) => { routeCoordinates.push([lnglat[0], lnglat[1]]); }); var padding; @@ -371,63 +451,16 @@ class Directions { this.elevation.loadingDomInDocument = false; this.elevation.setCoordinates(routeCoordinates); this.elevation.compute(e.data.routes[0].distance).then( () => { - const newDuration = GisUtils.getHikeTimeScarfsRule(this.results.options.distance, this.elevation.dplus, Globals.walkingSpeed); - this.results.updateDuration(newDuration); + if (this.configuration.profile === "pedestrian") { + const newDuration = GisUtils.getHikeTimeScarfsRule(this.results.options.distance, this.elevation.dplus, Globals.walkingSpeed); + this.results.updateDuration(newDuration); + } }); } } }); } - /** - * ecouteur lors de l'ajout d'un point avec addWayPoint() - * @see https://maplibre.org/maplibre-gl-directions/api/interfaces/MapLibreGlDirectionsWaypointEventData.html - * @param {*} e - * @returns - */ - #onAddWayPoint(e) { - var index = e.data.index; - if (!e.originalEvent) { - return; - } - var coordinates = e.originalEvent.lngLat; - Reverse.compute({ - lon : coordinates.lng, - lat : coordinates.lat - }).then(() => { - }).catch(() => { - }).finally(() => { - var target = null; - var coords = Reverse.getCoordinates() || {lon : coordinates.lng, lat : coordinates.lat}; - var address = Reverse.getAddress() || coords.lon.toFixed(6) + ", " + coords.lat.toFixed(6); - var strAddress = address; - if (typeof address !== "string") { - strAddress = ""; - strAddress += (address.number !== "") ? address.number + " " : ""; - strAddress += (address.street !== "") ? address.street + ", " : ""; - strAddress += address.city + ", " + address.postcode; - } - // start - if (index === 0) { - target = document.getElementById("directionsLocation_start"); - } - // end - if (index === 1) { - target = document.getElementById("directionsLocation_end"); - } - // step - if (index > 1) { - target = document.getElementById("directionsLocation_step_" + (index - 1)); - target.parentNode.parentNode.classList.remove("hidden"); - } - // on ajoute les resultats dans le contrôle - if (target) { - target.dataset.coordinates = "[" + coords.lon + "," + coords.lat + "]"; - target.value = strAddress; - } - }); - } - /** * ajoute la source et le layer à la carte pour affichage du preview */ @@ -473,7 +506,6 @@ class Directions { */ clear () { this.obj.clear(); - this.obj.off("addwaypoint", this.handleAddWayPoint); var locations = document.querySelectorAll(".inputDirectionsLocations"); for (let index = 0; index < locations.length; index++) { const element = locations[index]; diff --git a/src/js/onboarding-config.json b/src/js/onboarding-config.json index 4e0c05a1..f95d8644 100644 --- a/src/js/onboarding-config.json +++ b/src/js/onboarding-config.json @@ -1,4 +1,4 @@ { - "id": 3, - "html": "

Explorez les cartes thématiques IGN

Des cartes originales pour découvrir la France autrement.

J'ai compris
" + "id": 4, + "html": "

Découvrez votre nouveau calcul d'itinéraire à vélo.

Itinéraires vélo fiables et sécurisés avec notre partenaire Géovélo.

J'ai compris
" }