Skip to content

Instantly share code, notes, and snippets.

@timkelty
Last active February 13, 2020 15:10
Show Gist options
  • Select an option

  • Save timkelty/66f8ce06e32da8adb36776e28ff458bf to your computer and use it in GitHub Desktop.

Select an option

Save timkelty/66f8ce06e32da8adb36776e28ff458bf to your computer and use it in GitHub Desktop.
import React, {Component, createRef} from 'react';
import {Map as LeafletMap, TileLayer, withLeaflet} from 'react-leaflet';
import LeafletProviders from 'leaflet-providers';
import MarkerClusterGroup from 'react-leaflet-markercluster';
import Marker from '@components/leaflet/Marker.jsx';
import icons from '@js/leaflet/icons.js';
import 'leaflet/dist/leaflet.css';
import 'leaflet.markercluster/dist/MarkerCluster.css';
const northAmericaBounds = [
[57.326521225217064, -71.36718750000001],
[21.453068633086783, -125.85937500000001],
];
const Markers = ({
markers,
markerComponent: MarkerComponent,
}) => {
return [...markers].map((marker, index) => (
<MarkerComponent
key={index}
{...marker}
/>
));
};
class MapComponent extends Component {
_markers new Set(this.props.markers)
mapRef = createRef();
state = {
// markers: new Set(this.props.markers),
center: this.props.center,
zoom: this.props.zoom,
};
static defaultProps = {
markers: [],
center: null,
zoom: null,
style: {height: '500px'},
fitBoundsOptions: {
padding: [20, 20],
maxZoom: 10,
},
}
fitBounds(bounds, options = {}) {
if (!this.map) {
return;
}
this.map.fitBounds(bounds, Object.assign({}, this.props.fitBoundsOptions, options));
}
getMarkerBounds() {
return [...this.state.markers].map((marker) => marker.position);
}
addMarkers(markers) {
this.setState({
markers: new Set([...markers, ...this.state.markers]),
});
}
componentDidMount() {
this.map = this.mapRef.current.leafletElement;
const {center, markers} = this.state;
if (markers.size) {
this.addMarkers(markers);
if (!center) {
this.fitBounds(this.getMarkerBounds());
return;
}
}
if (!center) {
this.map.locate({
setView: true,
maxZoom: 7,
});
}
}
onLocationError = (e) => {
this.fitBounds(northAmericaBounds);
}
onMoveEnd = () => {
this.setState({
center: this.map.getCenter(),
zoom: this.map.getZoom(),
});
}
render() {
// Getting tile layer provider from this old busted package…
const provider = LeafletProviders.tileLayer.provider('Esri.WorldStreetMap');
const {
children,
markerComponent = Marker,
markerClusterGroupProps = {},
...mapProps
} = this.props;
const markersProps = {
markers: this.state.markers,
markerComponent,
};
return (
<LeafletMap
center={this.state.center}
zoom={this.state.zoom}
ref={this.mapRef}
onLocationError={this.onLocationError}
onMoveEnd={this.onMoveEnd}
onLoad={this.onLoad}
whenReady={this.whenReady}
scrollWheelZoom={false}
minZoom={2}
maxZoom={18}
worldCopyJump={true}
className='uk-position-z-index'
{...mapProps}
>
<TileLayer
// eslint-disable-next-line no-underscore-dangle
url={provider._url}
{...provider.options}
/>
<MarkerClusterGroup
maxClusterRadius={50}
disableClusteringAtZoom={14}
spiderfyDistanceMultiplier={2}
showCoverageOnHover={false}
zoomToBoundsOnClick={false}
iconCreateFunction={(cluster) => icons.cluster}
onClusterClick={(cluster) => {
cluster.layer.zoomToBounds({
padding: [20, 20],
maxZoom: 14,
});
}}
{...markerClusterGroupProps}
>
<Markers {...markersProps} />
</MarkerClusterGroup>
{children}
</LeafletMap>
);
}
}
export default MapComponent;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment