UNPKG

mapbox-gl

Version:
145 lines (128 loc) 5.37 kB
// @flow import DOM from '../../util/dom'; import { extend, bindAll } from '../../util/util'; import DragRotateHandler from '../handler/drag_rotate'; import type Map from '../map'; type Options = { showCompass?: boolean, showZoom?: boolean, visualizePitch?: boolean }; const defaultOptions: Options = { showCompass: true, showZoom: true, visualizePitch: false }; /** * A `NavigationControl` control contains zoom buttons and a compass. * * @implements {IControl} * @param {Object} [options] * @param {Boolean} [options.showCompass=true] If `true` the compass button is included. * @param {Boolean} [options.showZoom=true] If `true` the zoom-in and zoom-out buttons are included. * @param {Boolean} [options.visualizePitch=false] If `true` the pitch is visualized by rotating Y-axis of compass. * @example * var nav = new mapboxgl.NavigationControl(); * map.addControl(nav, 'top-left'); * @see [Display map navigation controls](https://www.mapbox.com/mapbox-gl-js/example/navigation/) * @see [Add a third party vector tile source](https://www.mapbox.com/mapbox-gl-js/example/third-party/) */ class NavigationControl { _map: Map; options: Options; _container: HTMLElement; _zoomInButton: HTMLElement; _zoomOutButton: HTMLElement; _compass: HTMLElement; _compassArrow: HTMLElement; _handler: DragRotateHandler; constructor(options: Options) { this.options = extend({}, defaultOptions, options); this._container = DOM.create('div', 'mapboxgl-ctrl mapboxgl-ctrl-group'); this._container.addEventListener('contextmenu', (e) => e.preventDefault()); if (this.options.showZoom) { bindAll([ '_updateZoomButtons' ], this); this._zoomInButton = this._createButton('mapboxgl-ctrl-icon mapboxgl-ctrl-zoom-in', 'Zoom in', () => this._map.zoomIn()); this._zoomOutButton = this._createButton('mapboxgl-ctrl-icon mapboxgl-ctrl-zoom-out', 'Zoom out', () => this._map.zoomOut()); } if (this.options.showCompass) { bindAll([ '_rotateCompassArrow' ], this); this._compass = this._createButton('mapboxgl-ctrl-icon mapboxgl-ctrl-compass', 'Reset bearing to north', () => { if (this.options.visualizePitch) { this._map.resetNorthPitch(); } else { this._map.resetNorth(); } }); this._compassArrow = DOM.create('span', 'mapboxgl-ctrl-compass-arrow', this._compass); } } _updateZoomButtons() { const zoom = this._map.getZoom(); if (zoom === this._map.getMaxZoom()) { this._zoomInButton.classList.add('mapboxgl-ctrl-icon-disabled'); } else { this._zoomInButton.classList.remove('mapboxgl-ctrl-icon-disabled'); } if (zoom === this._map.getMinZoom()) { this._zoomOutButton.classList.add('mapboxgl-ctrl-icon-disabled'); } else { this._zoomOutButton.classList.remove('mapboxgl-ctrl-icon-disabled'); } } _rotateCompassArrow() { const rotate = this.options.visualizePitch ? `rotateX(${this._map.transform.pitch}deg) rotateZ(${this._map.transform.angle * (180 / Math.PI)}deg)` : `rotate(${this._map.transform.angle}deg)`; this._compassArrow.style.transform = rotate; } onAdd(map: Map) { this._map = map; if (this.options.showZoom) { this._map.on('zoom', this._updateZoomButtons); this._updateZoomButtons(); } if (this.options.showCompass) { if (this.options.visualizePitch) { this._map.on('pitch', this._rotateCompassArrow); } this._map.on('rotate', this._rotateCompassArrow); this._rotateCompassArrow(); this._handler = new DragRotateHandler(map, {button: 'left', element: this._compass}); DOM.addEventListener(this._compass, 'mousedown', this._handler.onMouseDown); DOM.addEventListener(this._compass, 'touchstart', this._handler.onMouseDown, { passive: false }); this._handler.enable(); } return this._container; } onRemove() { DOM.remove(this._container); if (this.options.showZoom) { this._map.off('zoom', this._updateZoomButtons); } if (this.options.showCompass) { if (this.options.visualizePitch) { this._map.off('pitch', this._rotateCompassArrow); } this._map.off('rotate', this._rotateCompassArrow); DOM.removeEventListener(this._compass, 'mousedown', this._handler.onMouseDown); DOM.removeEventListener(this._compass, 'touchstart', this._handler.onMouseDown, { passive: false }); this._handler.disable(); delete this._handler; } delete this._map; } _createButton(className: string, ariaLabel: string, fn: () => mixed) { const a = DOM.create('button', className, this._container); a.type = 'button'; a.title = ariaLabel; a.setAttribute('aria-label', ariaLabel); a.addEventListener('click', fn); return a; } } export default NavigationControl;