From 063d8ef9eaf874a941f4459e831057dd0a1b7ddd Mon Sep 17 00:00:00 2001 From: Joris Date: Tue, 5 Jul 2022 21:55:41 +0200 Subject: Rewrite in TS --- src/map.ts | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 src/map.ts (limited to 'src/map.ts') diff --git a/src/map.ts b/src/map.ts new file mode 100644 index 0000000..04a1351 --- /dev/null +++ b/src/map.ts @@ -0,0 +1,131 @@ +import { h } from 'lib/h' +import * as Button from 'lib/button' +import * as ContextMenu from 'lib/contextMenu' +import * as Layout from 'lib/layout' +import * as Modal from 'lib/modal' +import * as Marker from 'marker' +import * as MarkerForm from 'markerForm' +import * as State from 'state' +import * as Serialization from 'serialization' +const L = window.L + +export function view() { + // Wait for elements to be on page before installing map + window.setTimeout(installMap, 0) + + return layout() +} + +const mapId: string = 'g-Map__Content' + +function layout(): Element { + return h('div', + { className: 'g-Layout__Page' }, + h('div', + { className: 'g-Layout__Header' }, + h('a', + { className: 'g-Layout__Home', + href: '#' + }, + 'Map' + ) + ) + , h('div', + { className: 'g-Map' }, + h('div', { id: mapId}) + ) + ) +} + +function installMap(): object { + + const map = L.map(mapId, { + center: [51.505, -0.09], + zoom: 2, + attributionControl: false + }) + + map.addLayer(L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png')) + + const mapMarkers = L.featureGroup() + map.addLayer(mapMarkers) + + map.addEventListener('contextmenu', e => { + ContextMenu.show( + e.originalEvent, + [ { label: 'Add a marker', + action: () => { + const pos = e.latlng + const lastMarker = State.last() + Modal.show(MarkerForm.view({ + onValidate: (color: string, icon: string, name: string, radius: number) => { + const id = State.add({ pos, color, icon, name, radius }) + Marker.add({ + id, + pos, + color, + icon, + name, + radius, + addToMap: marker => mapMarkers.addLayer(marker), + removeFromMap: marker => mapMarkers.removeLayer(marker) + }) + Modal.hide() + }, + onCancel: () => Modal.hide(), + color: lastMarker ? lastMarker.color : '#3F92CF', + icon: lastMarker ? lastMarker.icon : '', + name: '', + radius: 0, + })) + } + } + ] + ) + }) + + // Init from hash + const hash = window.location.hash.substr(1) + const state = Serialization.decode(hash) + State.reset(state) + addMarkers({ map, mapMarkers, state, isInit: true }) + + // Reload from hash + window.addEventListener('popstate', _ => reloadFromHash(map, mapMarkers)) + + return map +} + +export function reloadFromHash(map: L.Map, mapMarkers: L.FeatureGroup) { + const state = Serialization.decode(window.location.hash.substr(1)) + mapMarkers.clearLayers() + addMarkers({ map, mapMarkers, state, isInit: false }) +} + +interface AddMarkersOptions { + map: L.Map, + mapMarkers: L.FeatureGroup, + state: State.State, + isInit: boolean, +} + +function addMarkers({ map, mapMarkers, state, isInit }: AddMarkersOptions) { + state.forEach((marker, id) => { + const { pos, color, icon, name, radius } = marker + Marker.add({ + id, + pos, + color, + icon, + name, + radius, + addToMap: marker => mapMarkers.addLayer(marker), + removeFromMap: marker => mapMarkers.removeLayer(marker) + }) + }) + + // Focus + if (state.length > 0 && (isInit || !map.getBounds().contains(mapMarkers.getBounds()))) { + map.fitBounds(mapMarkers.getBounds(), { padding: [ 50, 50 ] }) + } +} -- cgit v1.2.3