UNPKG

leaflet-rotate

Version:

A Leaflet plugin that allows to add rotation functionality to map tiles

173 lines (138 loc) 5.23 kB
/** * A tri-state control for map rotation, states are: * * - Locked (default) * - Unlocked (user can pinch-rotate) * - Follow (rotation follows device orientation, if available) * * @typedef L.Control.Rotate */ L.Control.Rotate = L.Control.extend({ options: { position: 'topleft', closeOnZeroBearing: true }, onAdd: function(map) { var container = this._container = L.DomUtil.create('div', 'leaflet-control-rotate leaflet-bar'); // this.button = L.Control.Zoom.prototype._createButton.call(this, 'R', 'leaflet-control-rotate', 'leaflet-control-rotate', container, this._toggleLock); var arrow = this._arrow = L.DomUtil.create('span', 'leaflet-control-rotate-arrow'); arrow.style.backgroundImage = `url("data:image/svg+xml;charset=utf-8,%3Csvg width='29' height='29' viewBox='0 0 29 29' xmlns='http://www.w3.org/2000/svg' fill='%23333'%3E%3Cpath d='M10.5 14l4-8 4 8h-8z'/%3E%3Cpath d='M10.5 16l4 8 4-8h-8z' fill='%23ccc'/%3E%3C/svg%3E")`; arrow.style.cursor = 'grab'; arrow.style.display = 'block'; arrow.style.width = '100%'; arrow.style.height = '100%'; arrow.style.backgroundRepeat = 'no-repeat'; arrow.style.backgroundPosition = '50%'; // Copy-pasted from L.Control.Zoom var link = this._link = L.DomUtil.create('a', 'leaflet-control-rotate-toggle', container); link.appendChild(arrow); link.href = '#'; link.title = 'Rotate map'; L.DomEvent .on(link, 'dblclick', L.DomEvent.stopPropagation) .on(link, 'mousedown', this._handleMouseDown, this) .on(link, 'click', L.DomEvent.stop) .on(link, 'click', this._cycleState, this) .on(link, 'click', this._refocusOnMap, this); if (!L.Browser.any3d) { L.DomUtil.addClass(link, 'leaflet-disabled'); } this._restyle(); map.on('rotate', this._restyle, this); // State flag this._follow = false; this._canFollow = false; if (this.options.closeOnZeroBearing && map.getBearing() === 0) { container.style.display = 'none'; } return container; }, onRemove: function(map) { map.off('rotate', this._restyle, this); }, _handleMouseDown: function(e) { L.DomEvent.stop(e); this.dragging = true; this.dragstartX = e.pageX; this.dragstartY = e.pageY; L.DomEvent .on(document, 'mousemove', this._handleMouseDrag, this) .on(document, 'mouseup', this._handleMouseUp, this); }, _handleMouseUp: function(e) { L.DomEvent.stop(e); this.dragging = false; L.DomEvent .off(document, 'mousemove', this._handleMouseDrag, this) .off(document, 'mouseup', this._handleMouseUp, this); }, _handleMouseDrag: function(e) { if (!this.dragging) { return; } var deltaX = e.clientX - this.dragstartX; this._map.setBearing(deltaX); }, _cycleState: function(ev) { if (!this._map) { return; } var map = this._map; // Touch mode if (!map.touchRotate.enabled() && !map.compassBearing.enabled()) { map.touchRotate.enable(); } // Compass mode else if (!map.compassBearing.enabled()) { map.touchRotate.disable(); map.compassBearing.enable(); } // Locked mode else { map.compassBearing.disable(); map.setBearing(0); if (this.options.closeOnZeroBearing) { map.touchRotate.enable(); } } this._restyle(); }, _restyle: function() { if (!this._map.options.rotate) { L.DomUtil.addClass(this._link, 'leaflet-disabled'); } else { var map = this._map; var bearing = map.getBearing(); this._arrow.style.transform = 'rotate(' + bearing + 'deg)'; if (bearing && this.options.closeOnZeroBearing) { this._container.style.display = 'block'; } // Compass mode if (map.compassBearing.enabled()) { this._link.style.backgroundColor = 'orange'; } // Touch mode else if (map.touchRotate.enabled()) { this._link.style.backgroundColor = null; } // Locked mode else { this._link.style.backgroundColor = 'grey'; if (0 === bearing && this.options.closeOnZeroBearing) { this._container.style.display = 'none'; } } } }, }); L.control.rotate = function(options) { return new L.Control.Rotate(options); }; L.Map.mergeOptions({ rotateControl: true, }); L.Map.addInitHook(function() { if (this.options.rotateControl) { var options = typeof this.options.rotateControl === 'object' ? this.options.rotateControl : {}; this.rotateControl = L.control.rotate(options); this.addControl(this.rotateControl); } });