/* * Extends L.Map to handle zoom animations. */ L.Map.mergeOptions({ zoomAnimation: true, zoomAnimationThreshold: 4 }); if (L.DomUtil.TRANSITION) { L.Map.addInitHook(function () { // don't animate on browsers without hardware-accelerated transitions or old Android/Opera this._zoomAnimated = this.options.zoomAnimation && L.DomUtil.TRANSITION && L.Browser.any3d && !L.Browser.android23 && !L.Browser.mobileOpera; // zoom transitions run with the same duration for all layers, so if one of transitionend events // happens after starting zoom animation (propagating to the map pane), we know that it ended globally if (this._zoomAnimated) { L.DomEvent.on(this._mapPane, L.DomUtil.TRANSITION_END, this._catchTransitionEnd, this); } }); } L.Map.include(!L.DomUtil.TRANSITION ? {} : { _catchTransitionEnd: function (e) { if (this._animatingZoom && e.propertyName.indexOf('transform') >= 0) { this._onZoomTransitionEnd(); } }, _nothingToAnimate: function () { return !this._container.getElementsByClassName('leaflet-zoom-animated').length; }, _tryAnimatedZoom: function (center, zoom, options) { if (this._animatingZoom) { return true; } options = options || {}; // don't animate if disabled, not supported or zoom difference is too large if (!this._zoomAnimated || options.animate === false || this._nothingToAnimate() || Math.abs(zoom - this._zoom) > this.options.zoomAnimationThreshold) { return false; } // offset is the pixel coords of the zoom origin relative to the current center var scale = this.getZoomScale(zoom), offset = this._getCenterOffset(center)._divideBy(1 - 1 / scale), origin = this._getCenterLayerPoint()._add(offset); // don't animate if the zoom origin isn't within one screen from the current center, unless forced if (options.animate !== true && !this.getSize().contains(offset)) { return false; } this .fire('movestart') .fire('zoomstart'); this._animateZoom(center, zoom, origin, scale, null, true); return true; }, _animateZoom: function (center, zoom, origin, scale, delta, backwards, forTouchZoom) { if (!forTouchZoom) { this._animatingZoom = true; } // put transform transition on all layers with leaflet-zoom-animated class L.DomUtil.addClass(this._mapPane, 'leaflet-zoom-anim'); // remember what center/zoom to set after animation this._animateToCenter = center; this._animateToZoom = zoom; // disable any dragging during animation if (L.Draggable) { L.Draggable._disabled = true; } L.Util.requestAnimFrame(function () { this.fire('zoomanim', { center: center, zoom: zoom, origin: origin, scale: scale, delta: delta, backwards: backwards }); // horrible hack to work around a Chrome bug https://github.com/Leaflet/Leaflet/issues/3689 setTimeout(L.bind(this._onZoomTransitionEnd, this), 250); }, this); }, _onZoomTransitionEnd: function () { if (!this._animatingZoom) { return; } this._animatingZoom = false; L.DomUtil.removeClass(this._mapPane, 'leaflet-zoom-anim'); L.Util.requestAnimFrame(function () { this._resetView(this._animateToCenter, this._animateToZoom, true, true); if (L.Draggable) { L.Draggable._disabled = false; } }, this); } });