import './style.css';
import {Map, View} from 'ol';
import {fromLonLat, get, getTransform, toLonLat, transform} from 'ol/proj.js';
import {defaults as defaultControls} from 'ol/control.js';
import Overlay from 'ol/Overlay.js';
import { applyTransform } from 'ol/extent.js';
import ContextMenu from 'ol-contextmenu';
import ToggleMenuControl from './ui/controls.js';
import layerCategories from './layers/index.js';
// from https://openlayers.org/en/latest/examples/popup.html
const container = document.getElementById('popup');
const content = document.getElementById('popup-content');
const closer = document.getElementById('popup-closer');
const popupOverlay = new Overlay({
element: container,
autoPan: {
animation: {
duration: 250,
},
},
});
const contextMenu = new ContextMenu({
width: 170,
defaultItems: false,
items: [
{
text: 'Open on OSM',
callback: obj => {
const coords = transform(obj.coordinate, 'EPSG:3857', 'EPSG:4326')
window.open(
`https://www.openstreetmap.org/#map=${map.getView().getZoom()}/${coords[1]}/${coords[0]}`,
"_blank",
);
},
},
{
text: 'Copy lat/long',
callback: async function(obj){
const coords = transform(obj.coordinate, 'EPSG:3857', 'EPSG:4326')
try {
await navigator.clipboard.writeText(`${coords[1]}, ${coords[0]}`);
} catch (error) {
console.error(error.message);
}
},
},
{
text: 'Edit with iD',
callback: function(obj) {
const coords = toLonLat(obj.coordinate);
window.location.href = `https://www.openstreetmap.org/edit?editor=id#map=${map.getView().getZoom()}/${coords[1]}/${coords[0]}`;
},
},
{
text: 'Edit with JOSM',
callback: function(obj) {
const [minx, miny, maxx, maxy] = applyTransform(map.getView().calculateExtent(), getTransform('EPSG:3857', 'EPSG:4326'));
const url = `http://127.0.0.1:8111/load_and_zoom?left=${minx}&top=${maxy}&right=${maxx}&bottom=${miny}`;
// inspiration from
// https://github.com/openstreetmap/openstreetmap-website/blob/27f1fbcb580db21ca1276b9f2c40a6e1571cd90b/app/assets/javascripts/index.js#L257
const iframe = document.createElement('iframe');
iframe.setAttribute('src', url);
iframe.style.display = 'none';
console.log(iframe);
iframe.addEventListener('load', iframe.remove);
document.body.append(iframe);
},
}
],
});
const map = new Map({
controls: defaultControls().extend([new ToggleMenuControl(), contextMenu]),
target: 'map',
layers: [],
overlays: [popupOverlay],
view: new View({
center: fromLonLat([-93.24151, 44.80376]),
zoom: 10,
})
});
// Basic reactivity binding: like vue.js, just worse :)
//
// 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 = `
" + category.details + "${category.name}
${category.details ? "
${key} | ${value} |