diff options
author | Guilhem Moulin <guilhem@fripost.org> | 2025-10-17 12:44:47 +0200 |
---|---|---|
committer | Guilhem Moulin <guilhem@fripost.org> | 2025-10-18 12:56:52 +0200 |
commit | 7f74020caf44589bcd68a07378823848c6daea03 (patch) | |
tree | 3fff7765cc3bb74ebd15b9a0b48da522b97290f3 /main.js | |
parent | 9590ad0bd020d53d5e42489cdc9a44ce169b8a9f (diff) |
Use the geolocation API for the default location.
This is mostly useful on mobile platforms where the browser has access
to GPS. No need to load zoom #0 if one is in the forest and interested
how things look like just there.
Diffstat (limited to 'main.js')
-rw-r--r-- | main.js | 61 |
1 files changed, 51 insertions, 10 deletions
@@ -53,6 +53,8 @@ import RegularShape from 'ol/style/RegularShape.js'; import Stroke from 'ol/style/Stroke.js'; import Style from 'ol/style/Style.js'; +import Geolocation from 'ol/Geolocation.js'; + import proj4 from 'proj4'; import { get as getProjection } from 'ol/proj.js'; import { register as registerProjection } from 'ol/proj/proj4.js'; @@ -140,9 +142,6 @@ const [BASEMAP, MAP] = (function() { projection: PROJECTION, extent: EXTENT, showFullExtent: true, - /* center of the bbox of the Norrbotten and Västerbotten geometries */ - center: [694767.48, 7338176.57], - zoom: 1, enableRotation: false, resolutions: [1024, 512, 256, 128, 64, 32, 16, 8], constrainResolution: false, @@ -2693,15 +2692,57 @@ const LAYERS = Object.seal({ const STYLES = Object.seal(Object.fromEntries(Object.entries(LAYERS).map(([k,ls]) => [k, Object.seal(Object.fromEntries(Object.keys(ls).map((l) => [l, null])))]))); (function() { + const view = MAP.getView(); const params = new URLSearchParams(window.location.hash.substring(1)); - const x = parseFloat(params.get('x')); - const y = parseFloat(params.get('y')); + const x = parseFloat(params.get('x')), + y = parseFloat(params.get('y')), + z = parseFloat(params.get('z')); if (!isNaN(x) && !isNaN(y)) { - MAP.getView().setCenter([x, y]); - } - const z = parseFloat(params.get('z')); - if (!isNaN(z)) { - MAP.getView().setZoom(z); + view.setCenter([x, y]); + view.setZoom(isNaN(z) ? 1 : z); + } else { + /* center of the bbox of the Norrbotten and Västerbotten geometries */ + view.setCenter([694767.48, 7338176.57]); + view.setZoom(1); + const geolocation = new Geolocation({ + projection: view.getProjection(), + tracking: true, + }); + const evt_key = geolocation.on('change:position', function() { + const pos = geolocation.getPosition(); + if (pos == null) { + return; + } + /* ignore further geolocation position changes */ + unByKey(evt_key); + geolocation.setTracking(false); + + const params2 = new URLSearchParams(window.location.hash.substring(1)); + /* ignore geolocation result if coordinates have changed meanwhile */ + if (params2.has('x') || params2.has('y')) { + return; + } + /* ignore geolocation result if not within extent */ + if (EXTENT[0] > pos[0] || pos[0] > EXTENT[2] || EXTENT[1] > pos[1] || pos[1] > EXTENT[3]) { + return; + } + view.setCenter(pos); + params2.set('x', pos[0].toFixed(2).replace(TRAILING_ZEROES, '')); + params2.set('y', pos[1].toFixed(2).replace(TRAILING_ZEROES, '')); + if (!params2.has('z')) { + const accuracy = geolocation.getAccuracy(); + if (accuracy == null || accuracy < 0) { + view.setZoom(Math.max(view.getMinZoom(), 0)); + } else { + /* infer resolution from accuracy, up to zoom level 7 (8px/m) */ + const [width, height] = MAP.getSize(); + const res = 8. * accuracy / Math.min(width, height); + view.setResolution(Math.max(res, view.getResolutionForZoom(7))); + } + params2.set('z', view.getZoom().toFixed(3).replace(TRAILING_ZEROES, '')); + } + location.hash = '#' + params2.toString(); + }); } if (!params.has('layers') || (!params.get('layers').match(/^\s*$/) && /* compat redirect/layer subst for old non-hierachical names */ |