Add basic side menu for layer selection

This _should_ be smart and not load expensive layers until they're rendered.
This commit is contained in:
Chandler Swift 2023-07-03 19:26:02 -05:00
parent 7e9164c11f
commit ffaf53fee2
Signed by: chandlerswift
GPG key ID: A851D929D52FB93F
4 changed files with 96 additions and 14 deletions

View file

@ -8,6 +8,9 @@
</head> </head>
<body> <body>
<noscript>Sorry, but you'll need JavaScript enabled for any of this to work!</noscript> <noscript>Sorry, but you'll need JavaScript enabled for any of this to work!</noscript>
<aside>
<h1>Chandler's Maps</h1>
</aside>
<div id="map"></div> <div id="map"></div>
<script type="module" src="./main.js"></script> <script type="module" src="./main.js"></script>
</body> </body>

35
layers/index.js Normal file
View file

@ -0,0 +1,35 @@
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import amtrakLayer from './amtrak/layer.js';
import arenasLayer from './nhl-arenas/layer.js';
const layerCategories = [
{
name: "Base maps",
layers: [
{
name: "OpenStreetMap Carto",
enabled: true,
layer: new TileLayer({
source: new OSM(),
}),
},
],
},
{
name: "Overlays",
layers: [
{
name: "Amtrak Routes",
layer: amtrakLayer,
},
{
name: "NHL Arenas",
layer: arenasLayer,
},
]
}
];
export default layerCategories;

51
main.js
View file

@ -1,26 +1,51 @@
import './style.css'; import './style.css';
import {Map, View} from 'ol'; import {Map, View} from 'ol';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
import {fromLonLat} from 'ol/proj.js'; import {fromLonLat} from 'ol/proj.js';
import amtrakLayer from './layers/amtrak/layer.js'; import layerCategories from './layers/index.js';
import arenasLayer from './layers/nhl-arenas/layer.js';
const map = new Map({ const map = new Map({
target: 'map', target: 'map',
layers: [ layers: [],
new TileLayer({
source: new OSM()
})
],
view: new View({ view: new View({
center: fromLonLat([-93.24151, 44.80376]), center: fromLonLat([-93.24151, 44.80376]),
zoom: 10, zoom: 10,
}) })
}); });
map.getLayers().extend([ // Basic reactivity binding: like vue.js, just worse :)
amtrakLayer, //
arenasLayer, // This implements some basic reactivity so that I can add and remove layers.
]); // Nothing too fancy, at this point. Eventually, I'll likely pull in proper Vue,
// as I aim for more complex interactions, like layer ordering, color selection,
// custom layer imports, and more.
for (let category of layerCategories) {
const catDiv = document.createElement("div");
catDiv.innerHTML = `
<h3>${category.name}</h3>
<ul></ul>
`;
for (let layer of category.layers) {
const li = document.createElement("li");
li.innerHTML = `
<input type="checkbox" ${layer.enabled ? "checked" : ""}> ${layer.name}
`;
li.querySelector("input").addEventListener("change", function(e){
if (e.target.checked) {
map.getLayers().push(layer.layer);
} else {
map.getLayers().remove(layer.layer);
}
});
catDiv.querySelector("ul").appendChild(li);
}
document.querySelector("aside").appendChild(catDiv);
}
for (let category of layerCategories) {
for (let layer of category.layers) {
if (layer.enabled) {
map.addLayer(layer.layer);
}
}
}

View file

@ -8,5 +8,24 @@ html, body {
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
width: 100%; left: min(max(200px, 20%), 400px);
right: 0;
}
aside {
width: min(max(200px, 20%), 400px);
padding: 0 1em;
}
aside ul {
margin: 0;
padding: 0;
}
aside ul li {
list-style: none;
}
h1 {
text-align: center;
} }