aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilhem Moulin <guilhem@fripost.org>2025-10-17 12:44:47 +0200
committerGuilhem Moulin <guilhem@fripost.org>2025-10-18 12:56:52 +0200
commit7f74020caf44589bcd68a07378823848c6daea03 (patch)
tree3fff7765cc3bb74ebd15b9a0b48da522b97290f3
parent9590ad0bd020d53d5e42489cdc9a44ce169b8a9f (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.
-rw-r--r--main.js61
1 files changed, 51 insertions, 10 deletions
diff --git a/main.js b/main.js
index 874f88e..59f6143 100644
--- a/main.js
+++ b/main.js
@@ -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 */