UNPKG

mapbox-gl

Version:
190 lines (157 loc) 5.2 kB
'use strict'; const DOM = require('../../util/dom'); const LngLatBounds = require('../../geo/lng_lat_bounds'); const util = require('../../util/util'); const window = require('../../util/window'); /** * The `BoxZoomHandler` allows the user to zoom the map to fit within a bounding box. * The bounding box is defined by clicking and holding `shift` while dragging the cursor. * * @param {Map} map The Mapbox GL JS map to add the handler to. */ class BoxZoomHandler { constructor(map) { this._map = map; this._el = map.getCanvasContainer(); this._container = map.getContainer(); util.bindAll([ '_onMouseDown', '_onMouseMove', '_onMouseUp', '_onKeyDown' ], this); } /** * Returns a Boolean indicating whether the "box zoom" interaction is enabled. * * @returns {boolean} `true` if the "box zoom" interaction is enabled. */ isEnabled() { return !!this._enabled; } /** * Returns a Boolean indicating whether the "box zoom" interaction is active, i.e. currently being used. * * @returns {boolean} `true` if the "box zoom" interaction is active. */ isActive() { return !!this._active; } /** * Enables the "box zoom" interaction. * * @example * map.boxZoom.enable(); */ enable() { if (this.isEnabled()) return; this._el.addEventListener('mousedown', this._onMouseDown, false); this._enabled = true; } /** * Disables the "box zoom" interaction. * * @example * map.boxZoom.disable(); */ disable() { if (!this.isEnabled()) return; this._el.removeEventListener('mousedown', this._onMouseDown); this._enabled = false; } _onMouseDown(e) { if (!(e.shiftKey && e.button === 0)) return; window.document.addEventListener('mousemove', this._onMouseMove, false); window.document.addEventListener('keydown', this._onKeyDown, false); window.document.addEventListener('mouseup', this._onMouseUp, false); DOM.disableDrag(); this._startPos = DOM.mousePos(this._el, e); this._active = true; } _onMouseMove(e) { const p0 = this._startPos, p1 = DOM.mousePos(this._el, e); if (!this._box) { this._box = DOM.create('div', 'mapboxgl-boxzoom', this._container); this._container.classList.add('mapboxgl-crosshair'); this._fireEvent('boxzoomstart', e); } const minX = Math.min(p0.x, p1.x), maxX = Math.max(p0.x, p1.x), minY = Math.min(p0.y, p1.y), maxY = Math.max(p0.y, p1.y); DOM.setTransform(this._box, `translate(${minX}px,${minY}px)`); this._box.style.width = `${maxX - minX}px`; this._box.style.height = `${maxY - minY}px`; } _onMouseUp(e) { if (e.button !== 0) return; const p0 = this._startPos, p1 = DOM.mousePos(this._el, e), bounds = new LngLatBounds() .extend(this._map.unproject(p0)) .extend(this._map.unproject(p1)); this._finish(); if (p0.x === p1.x && p0.y === p1.y) { this._fireEvent('boxzoomcancel', e); } else { this._map .fitBounds(bounds, {linear: true}) .fire('boxzoomend', { originalEvent: e, boxZoomBounds: bounds }); } } _onKeyDown(e) { if (e.keyCode === 27) { this._finish(); this._fireEvent('boxzoomcancel', e); } } _finish() { this._active = false; window.document.removeEventListener('mousemove', this._onMouseMove, false); window.document.removeEventListener('keydown', this._onKeyDown, false); window.document.removeEventListener('mouseup', this._onMouseUp, false); this._container.classList.remove('mapboxgl-crosshair'); if (this._box) { this._box.parentNode.removeChild(this._box); this._box = null; } DOM.enableDrag(); } _fireEvent(type, e) { return this._map.fire(type, { originalEvent: e }); } } module.exports = BoxZoomHandler; /** * @typedef {Object} MapBoxZoomEvent * @property {MouseEvent} originalEvent * @property {LngLatBounds} boxZoomBounds The bounding box of the "box zoom" interaction. * This property is only provided for `boxzoomend` events. */ /** * Fired when a "box zoom" interaction starts. See [`BoxZoomHandler`](#BoxZoomHandler). * * @event boxzoomstart * @memberof Map * @instance * @property {MapBoxZoomEvent} data */ /** * Fired when a "box zoom" interaction ends. See [`BoxZoomHandler`](#BoxZoomHandler). * * @event boxzoomend * @memberof Map * @instance * @type {Object} * @property {MapBoxZoomEvent} data */ /** * Fired when the user cancels a "box zoom" interaction, or when the bounding box does not meet the minimum size threshold. * See [`BoxZoomHandler`](#BoxZoomHandler). * * @event boxzoomcancel * @memberof Map * @instance * @property {MapBoxZoomEvent} data */