UNPKG

mapbox-gl

Version:
108 lines (93 loc) 3.17 kB
// @flow import { bindAll } from '../util/util'; import window from '../util/window'; import throttle from '../util/throttle'; import type Map from './map'; /* * Adds the map's position to its page's location hash. * Passed as an option to the map object. * * @returns {Hash} `this` */ class Hash { _map: Map; _updateHash: () => ?TimeoutID; constructor() { bindAll([ '_onHashChange', '_updateHash' ], this); // Mobile Safari doesn't allow updating the hash more than 100 times per 30 seconds. this._updateHash = throttle(this._updateHashUnthrottled.bind(this), 30 * 1000 / 100); } /* * Map element to listen for coordinate changes * * @param {Object} map * @returns {Hash} `this` */ addTo(map: Map) { this._map = map; window.addEventListener('hashchange', this._onHashChange, false); this._map.on('moveend', this._updateHash); return this; } /* * Removes hash * * @returns {Popup} `this` */ remove() { window.removeEventListener('hashchange', this._onHashChange, false); this._map.off('moveend', this._updateHash); clearTimeout(this._updateHash()); delete this._map; return this; } getHashString(mapFeedback?: boolean) { const center = this._map.getCenter(), zoom = Math.round(this._map.getZoom() * 100) / 100, // derived from equation: 512px * 2^z / 360 / 10^d < 0.5px precision = Math.ceil((zoom * Math.LN2 + Math.log(512 / 360 / 0.5)) / Math.LN10), m = Math.pow(10, precision), lng = Math.round(center.lng * m) / m, lat = Math.round(center.lat * m) / m, bearing = this._map.getBearing(), pitch = this._map.getPitch(); let hash = ''; if (mapFeedback) { // new map feedback site has some constraints that don't allow // us to use the same hash format as we do for the Map hash option. hash += `#/${lng}/${lat}/${zoom}`; } else { hash += `#${zoom}/${lat}/${lng}`; } if (bearing || pitch) hash += (`/${Math.round(bearing * 10) / 10}`); if (pitch) hash += (`/${Math.round(pitch)}`); return hash; } _onHashChange() { const loc = window.location.hash.replace('#', '').split('/'); if (loc.length >= 3) { this._map.jumpTo({ center: [+loc[2], +loc[1]], zoom: +loc[0], bearing: +(loc[3] || 0), pitch: +(loc[4] || 0) }); return true; } return false; } _updateHashUnthrottled() { const hash = this.getHashString(); try { window.history.replaceState(window.history.state, '', hash); } catch (SecurityError) { // IE11 does not allow this if the page is within an iframe created // with iframe.contentWindow.document.write(...). // https://github.com/mapbox/mapbox-gl-js/issues/7410 } } } export default Hash;