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