1// @flow 2 3import DOM from '../../util/dom'; 4import {extend, bindAll} from '../../util/util'; 5import DragRotateHandler from '../handler/drag_rotate'; 6 7import type Map from '../map'; 8 9type Options = { 10 showCompass?: boolean, 11 showZoom?: boolean, 12 visualizePitch?: boolean 13}; 14 15const defaultOptions: Options = { 16 showCompass: true, 17 showZoom: true, 18 visualizePitch: false 19}; 20 21/** 22 * A `NavigationControl` control contains zoom buttons and a compass. 23 * 24 * @implements {IControl} 25 * @param {Object} [options] 26 * @param {Boolean} [options.showCompass=true] If `true` the compass button is included. 27 * @param {Boolean} [options.showZoom=true] If `true` the zoom-in and zoom-out buttons are included. 28 * @param {Boolean} [options.visualizePitch=false] If `true` the pitch is visualized by rotating X-axis of compass. 29 * @example 30 * var nav = new mapboxgl.NavigationControl(); 31 * map.addControl(nav, 'top-left'); 32 * @see [Display map navigation controls](https://www.mapbox.com/mapbox-gl-js/example/navigation/) 33 * @see [Add a third party vector tile source](https://www.mapbox.com/mapbox-gl-js/example/third-party/) 34 */ 35class NavigationControl { 36 _map: Map; 37 options: Options; 38 _container: HTMLElement; 39 _zoomInButton: HTMLElement; 40 _zoomOutButton: HTMLElement; 41 _compass: HTMLElement; 42 _compassArrow: HTMLElement; 43 _handler: DragRotateHandler; 44 45 constructor(options: Options) { 46 this.options = extend({}, defaultOptions, options); 47 48 this._container = DOM.create('div', 'mapboxgl-ctrl mapboxgl-ctrl-group'); 49 this._container.addEventListener('contextmenu', (e) => e.preventDefault()); 50 51 if (this.options.showZoom) { 52 bindAll([ 53 '_updateZoomButtons' 54 ], this); 55 this._zoomInButton = this._createButton('mapboxgl-ctrl-icon mapboxgl-ctrl-zoom-in', 'Zoom in', (e) => this._map.zoomIn({}, {originalEvent: e})); 56 this._zoomOutButton = this._createButton('mapboxgl-ctrl-icon mapboxgl-ctrl-zoom-out', 'Zoom out', (e) => this._map.zoomOut({}, {originalEvent: e})); 57 } 58 if (this.options.showCompass) { 59 bindAll([ 60 '_rotateCompassArrow' 61 ], this); 62 this._compass = this._createButton('mapboxgl-ctrl-icon mapboxgl-ctrl-compass', 'Reset bearing to north', (e) => { 63 if (this.options.visualizePitch) { 64 this._map.resetNorthPitch({}, {originalEvent: e}); 65 } else { 66 this._map.resetNorth({}, {originalEvent: e}); 67 } 68 }); 69 this._compassArrow = DOM.create('span', 'mapboxgl-ctrl-compass-arrow', this._compass); 70 } 71 } 72 73 _updateZoomButtons() { 74 const zoom = this._map.getZoom(); 75 if (zoom === this._map.getMaxZoom()) { 76 this._zoomInButton.classList.add('mapboxgl-ctrl-icon-disabled'); 77 } else { 78 this._zoomInButton.classList.remove('mapboxgl-ctrl-icon-disabled'); 79 } 80 if (zoom === this._map.getMinZoom()) { 81 this._zoomOutButton.classList.add('mapboxgl-ctrl-icon-disabled'); 82 } else { 83 this._zoomOutButton.classList.remove('mapboxgl-ctrl-icon-disabled'); 84 } 85 } 86 87 _rotateCompassArrow() { 88 const rotate = this.options.visualizePitch ? 89 `scale(${1 / Math.pow(Math.cos(this._map.transform.pitch * (Math.PI / 180)), 0.5)}) rotateX(${this._map.transform.pitch}deg) rotateZ(${this._map.transform.angle * (180 / Math.PI)}deg)` : 90 `rotate(${this._map.transform.angle * (180 / Math.PI)}deg)`; 91 92 this._compassArrow.style.transform = rotate; 93 } 94 95 onAdd(map: Map) { 96 this._map = map; 97 if (this.options.showZoom) { 98 this._map.on('zoom', this._updateZoomButtons); 99 this._updateZoomButtons(); 100 } 101 if (this.options.showCompass) { 102 if (this.options.visualizePitch) { 103 this._map.on('pitch', this._rotateCompassArrow); 104 } 105 this._map.on('rotate', this._rotateCompassArrow); 106 this._rotateCompassArrow(); 107 this._handler = new DragRotateHandler(map, {button: 'left', element: this._compass}
107); 108 DOM.addEventListener(this._compass, 'mousedown', this._handler.onMouseDown); 109 DOM.addEventListener(this._compass, 'touchstart', this._handler.onMouseDown, {passive: false}); 110 this._handler.enable(); 111 } 112 return this._container; 113 } 114 115 onRemove() { 116 DOM.remove(this._container); 117 if (this.options.showZoom) { 118 this._map.off('zoom', this._updateZoomButtons); 119 } 120 if (this.options.showCompass) { 121 if (this.options.visualizePitch) { 122 this._map.off('pitch', this._rotateCompassArrow); 123 } 124 this._map.off('rotate', this._rotateCompassArrow); 125 DOM.removeEventListener(this._compass, 'mousedown', this._handler.onMouseDown); 126 DOM.removeEventListener(this._compass, 'touchstart', this._handler.onMouseDown, {passive: false}); 127 this._handler.disable(); 128 delete this._handler; 129 } 130 131 delete this._map; 132 } 133 134 _createButton(className: string, ariaLabel: string, fn: () => mixed) { 135 const a = DOM.create('button', className, this._container); 136 a.type = 'button'; 137 a.title = ariaLabel; 138 a.setAttribute('aria-label', ariaLabel); 139 a.addEventListener('click', fn); 140 return a; 141 } 142} 143 144export default NavigationControl;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.