--- /dev/null
+L.Map.include(!L.DomUtil.TRANSITION ? {} : {\r
+ _zoomToIfCenterInView: function(center, zoom, centerOffset) {\r
+ \r
+ if (this._animatingZoom) { return true; }\r
+ if (!this.options.zoomAnimation) { return false; }\r
+ \r
+ var zoomDelta = zoom - this._zoom,\r
+ scale = Math.pow(2, zoomDelta),\r
+ offset = centerOffset.divideBy(1 - 1/scale);\r
+ \r
+ //if offset does not exceed half of the view\r
+ if (!this._offsetIsWithinView(offset, 1)) { return false; }\r
+ \r
+ this._mapPane.className += ' leaflet-zoom-anim';\r
+\r
+ var centerPoint = this.containerPointToLayerPoint(this.getSize().divideBy(2)),\r
+ origin = centerPoint.add(offset);\r
+ \r
+ this._prepareTileBg();\r
+ \r
+ this._runAnimation(center, zoom, scale, origin);\r
+ \r
+ return true;\r
+ },\r
+ \r
+ \r
+ _runAnimation: function(center, zoom, scale, origin) {\r
+ this._animatingZoom = true;\r
+\r
+ this._animateToCenter = center;\r
+ this._animateToZoom = zoom;\r
+ \r
+ var transform = L.DomUtil.TRANSFORM;\r
+ \r
+ //dumb FireFox hack, I have no idea why this magic zero translate fixes the scale transition problem\r
+ if (L.Browser.gecko || window.opera) {\r
+ this._tileBg.style[transform] += ' translate(0,0)';\r
+ }\r
+ \r
+ var scaleStr;\r
+ \r
+ // Android doesn't like translate/scale chains, transformOrigin + scale works better but \r
+ // it breaks touch zoom which Anroid doesn't support anyway, so that's a really ugly hack\r
+ // TODO work around this prettier\r
+ if (L.Browser.android) {\r
+ this._tileBg.style[transform + 'Origin'] = origin.x + 'px ' + origin.y + 'px';\r
+ scaleStr = 'scale(' + scale + ')';\r
+ } else {\r
+ scaleStr = L.DomUtil.getScaleString(scale, origin);\r
+ }\r
+ \r
+ L.Util.falseFn(this._tileBg.offsetWidth); //hack to make sure transform is updated before running animation\r
+ \r
+ var options = {};\r
+ options[transform] = this._tileBg.style[transform] + ' ' + scaleStr;\r
+ this._tileBg.transition.run(options);\r
+ },\r
+ \r
+ _prepareTileBg: function() {\r
+ if (!this._tileBg) {\r
+ this._tileBg = this._createPane('leaflet-tile-pane', this._mapPane);\r
+ this._tileBg.style.zIndex = 1;\r
+ }\r
+\r
+ var tilePane = this._tilePane,\r
+ tileBg = this._tileBg;\r
+ \r
+ // prepare the background pane to become the main tile pane\r
+ //tileBg.innerHTML = '';\r
+ tileBg.style[L.DomUtil.TRANSFORM] = '';\r
+ tileBg.style.visibility = 'hidden';\r
+ \r
+ // tells tile layers to reinitialize their containers\r
+ tileBg.empty = true;\r
+ tilePane.empty = false;\r
+\r
+ this._tilePane = this._panes.tilePane = tileBg;\r
+ this._tileBg = tilePane;\r
+ \r
+ if (!this._tileBg.transition) {\r
+ this._tileBg.transition = new L.Transition(this._tileBg, {duration: 0.3, easing: 'cubic-bezier(0.25,0.1,0.25,0.75)'});\r
+ this._tileBg.transition.on('end', this._onZoomTransitionEnd, this);\r
+ }\r
+ \r
+ this._stopLoadingBgTiles();\r
+ },\r
+ \r
+ // stops loading all tiles in the background layer\r
+ _stopLoadingBgTiles: function() {\r
+ var tiles = [].slice.call(this._tileBg.getElementsByTagName('img'));\r
+ \r
+ for (var i = 0, len = tiles.length; i < len; i++) {\r
+ if (!tiles[i].complete) {\r
+ tiles[i].src = '';\r
+ tiles[i].parentNode.removeChild(tiles[i]);\r
+ }\r
+ }\r
+ },\r
+ \r
+ _onZoomTransitionEnd: function() {\r
+ this._restoreTileFront();\r
+ \r
+ L.Util.falseFn(this._tileBg.offsetWidth);\r
+ this._resetView(this._animateToCenter, this._animateToZoom, true);\r
+ \r
+ //TODO clear tileBg on map layersload\r
+ \r
+ this._mapPane.className = this._mapPane.className.replace(' leaflet-zoom-anim', ''); //TODO toggleClass util\r
+ this._animatingZoom = false;\r
+ },\r
+ \r
+ _restoreTileFront: function() {\r
+ this._tilePane.innerHTML = '';\r
+ this._tilePane.style.visibility = '';\r
+ this._tilePane.style.zIndex = 2;\r
+ this._tileBg.style.zIndex = 1;\r
+ },\r
+ \r
+ _clearTileBg: function() {\r
+ if (!this._animatingZoom && !this.touchZoom._zooming) {\r
+ this._tileBg.innerHTML = '';\r
+ }\r
+ }\r
+});
\ No newline at end of file