You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
62 lines
1.9 KiB
62 lines
1.9 KiB
import React, { useEffect, useState } from 'react'; |
|
|
|
import { makeStyles } from '@material-ui/core/styles'; |
|
import Box from '@material-ui/core/Box'; |
|
|
|
import "leaflet/dist/leaflet.css" |
|
|
|
import L from 'leaflet'; |
|
|
|
export function MapView(props) { |
|
// This is bad React design: this component holds state which the parent needs (the Leaflet map object). |
|
// Normally we'd make such an object in the parent and pass it as a prop. However, the object cannot |
|
// be created without a div being present for it to reside in, so we have a chicken-egg problem. |
|
// We solve it by loading the map after mounting this component, then passing a handle to the parent. |
|
const { onMapChange, style } = props; |
|
const [map, setMap] = useState(null); |
|
const [camera, setCameraNoPush] = useState([51.505, -0.09, 13]); //lat, long, zoom |
|
|
|
var _ = require('lodash'); |
|
const id = _.uniqueId("leaflet_map_"); |
|
|
|
function updateCamera() { |
|
var c = map.getCenter(); |
|
var z = map.getZoom(); |
|
setCameraNoPush([c[0], c[1], z]); |
|
} |
|
|
|
// Initialize the map on mount. |
|
useEffect(() => { |
|
setMap(L.map(id, { |
|
center: [camera[0], camera[1]], |
|
zoom: camera[2], |
|
layers: [ |
|
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { |
|
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' |
|
}), |
|
] |
|
} |
|
)); |
|
}, []) |
|
|
|
// Notify parent if map object changes. |
|
useEffect(() => { |
|
if (onMapChange) { |
|
onMapChange(map); |
|
} |
|
}, map); |
|
|
|
// Update camera state of this component when map changes. |
|
useEffect(() => { |
|
if (map != null) { |
|
map.on('move', function (e) { |
|
updateCamera(); |
|
}); |
|
map.on('zoom', function (e) { |
|
updateCamera(); |
|
}); |
|
} |
|
}, [map]) |
|
|
|
return <div id={id} style={style}></div> |
|
} |