UNPKG

leaflet

Version:

JavaScript library for mobile-friendly interactive maps

109 lines (79 loc) 3.12 kB
/* * L.Handler.TouchZoom is used by L.Map to add pinch zoom on supported mobile browsers. */ L.Map.mergeOptions({ touchZoom: L.Browser.touch && !L.Browser.android23, bounceAtZoomLimits: true }); L.Map.TouchZoom = L.Handler.extend({ addHooks: function () { L.DomEvent.on(this._map._container, 'touchstart', this._onTouchStart, this); }, removeHooks: function () { L.DomEvent.off(this._map._container, 'touchstart', this._onTouchStart, this); }, _onTouchStart: function (e) { var map = this._map; if (!e.touches || e.touches.length !== 2 || map._animatingZoom || this._zooming) { return; } var p1 = map.mouseEventToContainerPoint(e.touches[0]), p2 = map.mouseEventToContainerPoint(e.touches[1]); this._centerPoint = map.getSize()._divideBy(2); this._startLatLng = map.containerPointToLatLng(this._centerPoint); if (map.options.touchZoom !== 'center') { this._pinchStartLatLng = map.containerPointToLatLng(p1.add(p2)._divideBy(2)); } this._startDist = p1.distanceTo(p2); this._startZoom = map.getZoom(); this._moved = false; this._zooming = true; map.stop(); L.DomEvent .on(document, 'touchmove', this._onTouchMove, this) .on(document, 'touchend', this._onTouchEnd, this); L.DomEvent.preventDefault(e); }, _onTouchMove: function (e) { if (!e.touches || e.touches.length !== 2 || !this._zooming) { return; } var map = this._map, p1 = map.mouseEventToContainerPoint(e.touches[0]), p2 = map.mouseEventToContainerPoint(e.touches[1]), scale = p1.distanceTo(p2) / this._startDist; this._zoom = map.getScaleZoom(scale, this._startZoom); if (map.options.touchZoom === 'center') { this._center = this._startLatLng; if (scale === 1) { return; } } else { // Get delta from pinch to center, so centerLatLng is delta applied to initial pinchLatLng var delta = p1._add(p2)._divideBy(2)._subtract(this._centerPoint); if (scale === 1 && delta.x === 0 && delta.y === 0) { return; } this._center = map.unproject(map.project(this._pinchStartLatLng).subtract(delta)); } if (!map.options.bounceAtZoomLimits) { if ((this._zoom <= map.getMinZoom() && scale < 1) || (this._zoom >= map.getMaxZoom() && scale > 1)) { return; } } if (!this._moved) { map._moveStart(true); this._moved = true; } L.Util.cancelAnimFrame(this._animRequest); var moveFn = L.bind(map._move, map, this._center, this._zoom, {pinch: true, round: false}); this._animRequest = L.Util.requestAnimFrame(moveFn, this, true); L.DomEvent.preventDefault(e); }, _onTouchEnd: function () { if (!this._moved || !this._zooming) { this._zooming = false; return; } this._zooming = false; L.Util.cancelAnimFrame(this._animRequest); L.DomEvent .off(document, 'touchmove', this._onTouchMove) .off(document, 'touchend', this._onTouchEnd); var zoom = this._zoom; zoom = this._map._limitZoom(zoom - this._startZoom > 0 ? Math.ceil(zoom) : Math.floor(zoom)); this._map._animateZoom(this._center, zoom, true, true); } }); L.Map.addInitHook('addHandler', 'touchZoom', L.Map.TouchZoom);