aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--index.html11
-rw-r--r--main.js104
-rw-r--r--package-lock.json45
-rw-r--r--package.json2
-rw-r--r--style.css21
-rw-r--r--vite.config.js2
6 files changed, 151 insertions, 34 deletions
diff --git a/index.html b/index.html
index ce90018..d6be025 100644
--- a/index.html
+++ b/index.html
@@ -7,6 +7,17 @@
</head>
<body>
<div id="map"></div>
+ <div id="layer-selection-btn" class="ol-control ol-unselectable">
+ <button type="button" aria-expanded="false" title="Byt kartlager">
+ <i class="bi bi-stack"></i>
+ </button>
+ </div>
+ <div id="layer-selection-dialog" class="ol-control map-dialog map-dialog-hidden">
+ <div class="form-check form-switch">
+ <input class="form-check-input" type="checkbox" role="switch" id="layer-topowebb_nedtonad">
+ <label class="form-check-label" for="layer-topowebb_nedtonad">Nedtonad bakgrund karta</label>
+ </div>
+ </div>
<script type="module" src="./main.js"></script>
</body>
</html>
diff --git a/main.js b/main.js
index f1d36e9..dd365e3 100644
--- a/main.js
+++ b/main.js
@@ -22,6 +22,10 @@ import TileLayer from 'ol/layer/Tile.js';
import WMTS from 'ol/source/WMTS.js';
import WMTSTileGrid from 'ol/tilegrid/WMTS.js';
+import Zoom from 'ol/control/Zoom.js';
+import Attribution from 'ol/control/Attribution.js';
+import Control from 'ol/control/Control.js';
+
import proj4 from 'proj4';
import {get as getProjection} from 'ol/proj.js';
import {register as registerProjection} from 'ol/proj/proj4.js';
@@ -49,7 +53,56 @@ const projection = getProjection('EPSG:3006');
*/
const extent = [110720, 6927136, 1159296, 7975712];
+/* XXX using the topowebbcache WMTS is fine for testing (as it
+ * doesn't require authentication) but not in production in a public
+ * instance as doing so would violate its current terms of use (as
+ * of January 2024 it's not CC0 open data). See
+ *
+ * https://www.lantmateriet.se/sv/om-lantmateriet/Rattsinformation/upphovsratt-och-publicering-av-lantmateriets-geografiska-information/
+ * https://www.lantmateriet.se/sv/kartor/vara-karttjanster/min-karta/#anchor-2
+ * https://help.locusmap.eu/topic/support-for-swedish-lantmateriets-min-karta-wms
+ *
+ * More precise background maps might be available in the future
+ * as open data, though:
+ *
+ * https://www.lantmateriet.se/sv/om-lantmateriet/press/nyheter/lantmateriets-arbete-mot-oppna-data-i-full-gang/
+ */
+const baseMapSource = new WMTS({
+ // XXX the 'layer' parameter should be passed in the options
+ // dictionary (like style and version), but there is no setLayer()
+ // method to switch from/to the toned down map
+ url: 'https://minkarta.lantmateriet.se/map/topowebbcache?layer=topowebb',
+ version: '1.0.0',
+ style: 'default',
+ matrixSet: '3006',
+ format: 'image/png',
+ tileGrid: new WMTSTileGrid({
+ extent: extent,
+ // https://www.lantmateriet.se/globalassets/geodata/geodatatjanster/tb_twk_visning_cache_v1.1.0.pdf
+ tileSize: 256,
+ origin: [-1200000, 8500000],
+ resolutions: [4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, .5],
+ matrixIds: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
+ }),
+ projection: projection,
+ wrapX: false,
+ crossOrigin: 'anonymous',
+ attributions: '&copy; <a href="https://lantmateriet.se" target="_blank">Lantmäteriet</a>',
+});
+
+
const map = new Map({
+ controls: [
+ new Zoom({
+ zoomInTipLabel: 'Zooma in',
+ zoomOutTipLabel: 'Zooma ut',
+ }),
+ new Attribution({
+ collapsible: true,
+ collapsed: true,
+ tipLabel: 'Information',
+ }),
+ ],
view: new View({
projection: projection,
extent: extent,
@@ -63,41 +116,24 @@ const map = new Map({
}),
layers: [
new TileLayer({
- /* XXX using the topowebbcache WMTS is fine for testing (as it
- * doesn't require authentication) but not in production in a public
- * instance as doing so would violate its current terms of use (as
- * of January 2024 it's not CC0 open data). See
- *
- * https://www.lantmateriet.se/sv/om-lantmateriet/Rattsinformation/upphovsratt-och-publicering-av-lantmateriets-geografiska-information/
- * https://www.lantmateriet.se/sv/kartor/vara-karttjanster/min-karta/#anchor-2
- * https://help.locusmap.eu/topic/support-for-swedish-lantmateriets-min-karta-wms
- *
- * More precise background maps might be available in the future
- * as open data, though:
- *
- * https://www.lantmateriet.se/sv/om-lantmateriet/press/nyheter/lantmateriets-arbete-mot-oppna-data-i-full-gang/
- */
- source: new WMTS({
- url: 'https://minkarta.lantmateriet.se/map/topowebbcache',
- version: '1.0.0',
- layer: 'topowebb',
- style: 'default',
- matrixSet: '3006',
- format: 'image/png',
- tileGrid: new WMTSTileGrid({
- extent: extent,
- // https://www.lantmateriet.se/globalassets/geodata/geodatatjanster/tb_twk_visning_cache_v1.1.0.pdf
- tileSize: 256,
- origin: [-1200000, 8500000],
- resolutions: [4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, .5],
- matrixIds: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13],
- }),
- projection: projection,
- wrapX: false,
- crossOrigin: 'anonymous',
- attributions: '&copy; <a href="https://lantmateriet.se" target="_blank">Lantmäteriet</a>',
- }),
+ source: baseMapSource
}),
],
target: document.getElementById('map'),
});
+
+(function() {
+ const element = document.getElementById('layer-selection-btn');
+ map.addControl(new Control({
+ element: element,
+ }));
+ element.onclick = function(event) {
+ document.getElementById('layer-selection-dialog').classList.toggle('map-dialog-hidden');
+ element.classList.toggle('map-dialog-expanded');
+ };
+})();
+
+document.getElementById('layer-topowebb_nedtonad').onchange = function(event) {
+ const layer = event.target.checked ? 'topowebb_nedtonad' : 'topowebb';
+ baseMapSource.setUrl('https://minkarta.lantmateriet.se/map/topowebbcache?LAYER=' + layer);
+}
diff --git a/package-lock.json b/package-lock.json
index 50f9d55..27ac98e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,6 +9,8 @@
"version": "0.0.1",
"license": "AGPL-3.0-or-later",
"dependencies": {
+ "bootstrap": "5.3.x",
+ "bootstrap-icons": "1.11.x",
"ol": "8.2.x",
"proj4": "2.9.x"
},
@@ -389,6 +391,16 @@
"resolved": "https://registry.npmjs.org/@petamoriken/float16/-/float16-3.8.4.tgz",
"integrity": "sha512-kB+NJ5Br56ZhElKsf0pM7/PQfrDdDVMRz8f0JM6eVOGE+L89z9hwcst9QvWBBnazzuqGTGtPsJNZoQ1JdNiGSQ=="
},
+ "node_modules/@popperjs/core": {
+ "version": "2.11.8",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
+ "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
+ "peer": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/popperjs"
+ }
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.9.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.4.tgz",
@@ -564,6 +576,39 @@
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true
},
+ "node_modules/bootstrap": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz",
+ "integrity": "sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/twbs"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/bootstrap"
+ }
+ ],
+ "peerDependencies": {
+ "@popperjs/core": "^2.11.8"
+ }
+ },
+ "node_modules/bootstrap-icons": {
+ "version": "1.11.3",
+ "resolved": "https://registry.npmjs.org/bootstrap-icons/-/bootstrap-icons-1.11.3.tgz",
+ "integrity": "sha512-+3lpHrCw/it2/7lBL15VR0HEumaBss0+f/Lb6ZvHISn1mlK83jjFpooTLsMWbIjJMDjDjOExMsTxnXSIT4k4ww==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/twbs"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/bootstrap"
+ }
+ ]
+ },
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
diff --git a/package.json b/package.json
index bf89a66..02b0c8f 100644
--- a/package.json
+++ b/package.json
@@ -11,6 +11,8 @@
"vite": "5.x"
},
"dependencies": {
+ "bootstrap": "5.3.x",
+ "bootstrap-icons": "1.11.x",
"ol": "8.2.x",
"proj4": "2.9.x"
}
diff --git a/style.css b/style.css
index be58089..d66db40 100644
--- a/style.css
+++ b/style.css
@@ -1,3 +1,5 @@
+@import "~bootstrap/dist/css/bootstrap.css";
+@import "~bootstrap-icons/font/bootstrap-icons.css";
@import "~ol/ol.css";
html, body {
@@ -10,3 +12,22 @@ html, body {
bottom: 0;
width: 100%;
}
+#layer-selection-btn {
+ right: .5em;
+ top: .5em;
+}
+.map-dialog-hidden {
+ display: none;
+}
+.map-dialog {
+ top: .5em;
+ right: calc(.5em + 1.375em + 2px + .2em);
+ background: var(--ol-partial-background-color);
+ border: 1px solid var(--ol-subtle-background-color);
+ padding: 1ex;
+}
+@media screen and (max-width: 500px) {
+ #layer-selection-btn {
+ display: none;
+ }
+}
diff --git a/vite.config.js b/vite.config.js
index 12d656b..668b49f 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -9,6 +9,8 @@ export default {
},
resolve: {
alias: {
+ "~bootstrap": "node_modules/bootstrap",
+ "~bootstrap-icons": "node_modules/bootstrap-icons",
"~ol": "node_modules/ol",
}
},