UNPKG

react-map-gl

Version:

A React wrapper for MapboxGL-js and overlay API.

195 lines (165 loc) 6.49 kB
import _defineProperty from "@babel/runtime/helpers/esm/defineProperty"; import { createElement, createRef } from 'react'; import PropTypes from 'prop-types'; import WebMercatorViewport from 'viewport-mercator-project'; import mapboxgl from '../utils/mapboxgl'; import BaseControl from './base-control'; import Marker from './marker'; import MapState from '../utils/map-state'; import TransitionManager from '../utils/transition-manager'; import { isGeolocationSupported } from '../utils/geolocate-utils'; const LINEAR_TRANSITION_PROPS = Object.assign({}, TransitionManager.defaultProps, { transitionDuration: 500 }); const noop = () => {}; const propTypes = Object.assign({}, BaseControl.propTypes, { className: PropTypes.string, style: PropTypes.object, positionOptions: PropTypes.object, fitBoundsOptions: PropTypes.object, trackUserLocation: PropTypes.bool, showUserLocation: PropTypes.bool, onViewStateChange: PropTypes.func, onViewportChange: PropTypes.func }); const defaultProps = Object.assign({}, BaseControl.defaultProps, { className: '', style: {}, positionOptions: null, fitBoundsOptions: null, trackUserLocation: false, showUserLocation: true }); export default class GeolocateControl extends BaseControl { constructor() { super(...arguments); _defineProperty(this, "state", { supportsGeolocation: false, markerPosition: null }); _defineProperty(this, "_mapboxGeolocateControl", null); _defineProperty(this, "_geolocateButtonRef", createRef()); _defineProperty(this, "_markerRef", createRef()); _defineProperty(this, "_setupMapboxGeolocateControl", supportsGeolocation => { if (!supportsGeolocation) { console.warn('Geolocation support is not available, the GeolocateControl will not be visible.'); return; } const controlOptions = {}; ['positionOptions', 'fitBoundsOptions', 'trackUserLocation', 'showUserLocation'].forEach(prop => { if (prop in this.props && this.props[prop] !== null) { controlOptions[prop] = this.props[prop]; } }); this._mapboxGeolocateControl = new mapboxgl.GeolocateControl(controlOptions); this._mapboxGeolocateControl._watchState = 'OFF'; this._mapboxGeolocateControl._geolocateButton = this._geolocateButtonRef.current; this._mapboxGeolocateControl._updateMarker = this._updateMarker; this._mapboxGeolocateControl._updateCamera = this._updateCamera; this._mapboxGeolocateControl._setup = true; }); _defineProperty(this, "_onClickGeolocate", () => { return this._mapboxGeolocateControl.trigger(); }); _defineProperty(this, "_updateMarker", position => { if (position) { this.setState({ markerPosition: position.coords }); } }); _defineProperty(this, "_getBounds", position => { const center = new mapboxgl.LngLat(position.coords.longitude, position.coords.latitude); const radius = position.coords.accuracy; const bounds = center.toBounds(radius); return [[bounds._ne.lng, bounds._ne.lat], [bounds._sw.lng, bounds._sw.lat]]; }); _defineProperty(this, "_updateCamera", position => { const viewport = this._context.viewport; const bounds = this._getBounds(position); const _fitBounds = new WebMercatorViewport(viewport).fitBounds(bounds), longitude = _fitBounds.longitude, latitude = _fitBounds.latitude, zoom = _fitBounds.zoom; const newViewState = Object.assign({}, viewport, { longitude, latitude, zoom }); const mapState = new MapState(newViewState); const viewState = Object.assign({}, mapState.getViewportProps(), LINEAR_TRANSITION_PROPS); const onViewportChange = this.props.onViewportChange || this._context.onViewportChange || noop; const onViewStateChange = this.props.onViewStateChange || this._context.onViewStateChange || noop; onViewStateChange({ viewState }); onViewportChange(viewState); }); _defineProperty(this, "_renderButton", (type, label, callback) => { return createElement('button', { key: type, className: "mapboxgl-ctrl-icon mapboxgl-ctrl-".concat(type), ref: this._geolocateButtonRef, type: 'button', title: label, onClick: callback }); }); _defineProperty(this, "_renderMarker", () => { const showUserLocation = this.props.showUserLocation; const markerPosition = this.state.markerPosition; if (!showUserLocation || !markerPosition) { return null; } return createElement(Marker, { key: 'location-maker', ref: this._markerRef, className: 'mapboxgl-user-location-dot', longitude: markerPosition.longitude, latitude: markerPosition.latitude, onContextMenu: e => e.preventDefault(), captureDrag: false, captureDoubleClick: false }); }); } componentDidMount() { isGeolocationSupported().then(result => { this.setState({ supportsGeolocation: result }); this._setupMapboxGeolocateControl(result); }); } componentDidUpdate() { const markerRef = this._markerRef.current; if (this._mapboxGeolocateControl && markerRef) { this._mapboxGeolocateControl._dotElement = markerRef._containerRef.current; } } componentWillUnmount() { const geolocationWatchID = this._mapboxGeolocateControl._geolocationWatchID; if (geolocationWatchID !== undefined) { window.navigator.geolocation.clearWatch(geolocationWatchID); this._mapboxGeolocateControl._geolocationWatchID = undefined; } } _render() { if (!this.state.supportsGeolocation) { return null; } const _this$props = this.props, className = _this$props.className, style = _this$props.style; return createElement('div', null, [this._renderMarker(), createElement('div', { key: 'geolocate-control', className: "mapboxgl-ctrl mapboxgl-ctrl-group ".concat(className), ref: this._containerRef, style, onContextMenu: e => e.preventDefault() }, this._renderButton('geolocate', 'Geolocate', this._onClickGeolocate))]); } } _defineProperty(GeolocateControl, "propTypes", propTypes); _defineProperty(GeolocateControl, "defaultProps", defaultProps); //# sourceMappingURL=geolocate-control.js.map