Permalink
Browse files

zoom animation fix and refactoring, works like a charm on iOS now!

  • Loading branch information...
mourner committed Mar 31, 2011
1 parent a008245 commit 9d93998ba255d788cae1fddf2411fca18ca95ef9
Showing with 77 additions and 67 deletions.
  1. +0 −1 README.md
  2. +4 −1 debug/map-mobile.html
  3. +1 −4 dist/leaflet.css
  4. +13 −12 dist/leaflet.js
  5. +19 −15 src/handler/TouchZoom.js
  6. +4 −2 src/map/Map.js
  7. +36 −32 src/map/ext/Map.ZoomAnimation.js
View
@@ -28,7 +28,6 @@ Controls:
Known issues to be fixed:
- flickering of vector layers on drag end under mobile webkit
- - show scaled background until tiles are loaded on mobile webkit
## Browser support
View
@@ -17,14 +17,17 @@
width: 100%;
height: 100%;
}
+
.leaflet-tile {
- visibility: visible;
+ visibility: inherit;
opacity: 0;
-webkit-transition: opacity 0.2s linear;
}
.leaflet-tile-loaded {
opacity: 1;
}
+
+
.leaflet-popup {
-webkit-transition: opacity 0.2s linear;
opacity: 0;
View
@@ -46,10 +46,7 @@
.leaflet-marker-pane { z-index: 5; }
.leaflet-popup-pane { z-index: 6; }
-.leaflet-animating .leaflet-marker-pane,
-.leaflet-animating .leaflet-shadow-pane,
-.leaflet-animating .leaflet-popup-pane,
-.leaflet-animating .leaflet-overlay-pane {
+.leaflet-animating .leaflet-objects-pane {
visibility: hidden;
}
View

Large diffs are not rendered by default.

Oops, something went wrong.
View
@@ -24,9 +24,10 @@ L.Handler.TouchZoom = L.Handler.extend({
this._startCenter = p1.add(p2).divideBy(2, true);
this._startDist = p1.distanceTo(p2);
- this._startTransform = this._map._mapPane.style.webkitTransform;
+ //this._startTransform = this._map._mapPane.style.webkitTransform;
this._moved = false;
+ this._zooming = true;
this._centerOffset = viewCenter.subtract(this._startCenter);
@@ -40,8 +41,8 @@ L.Handler.TouchZoom = L.Handler.extend({
if (!e.touches || e.touches.length != 2) { return; }
if (!this._moved) {
- //TODO do this more gracefully
- this._map._panes.popupPane.style.display = 'none';
+ this._map._mapPane.className += ' leaflet-animating';
+ this._map._prepareTileBg();
this._moved = true;
}
@@ -56,11 +57,7 @@ L.Handler.TouchZoom = L.Handler.extend({
* it didn't count the origin on the first touch-zoom but worked correctly afterwards
*/
- /*this._map._mapPane.style.webkitTransformOrigin =
- this._startCenter.x + 'px ' + this._startCenter.y + 'px';*/
-
- this._map._mapPane.style.webkitTransform = [
- this._startTransform,
+ this._map._tileBg.style.webkitTransform = [
L.DomUtil.getTranslateString(this._delta),
L.DomUtil.getScaleString(this._scale, this._startCenter)
].join(" ");
@@ -69,19 +66,26 @@ L.Handler.TouchZoom = L.Handler.extend({
},
_onTouchEnd: function(e) {
- if (!e.touches || e.touches.length >= 2 || !this._scale) { return; }
+ if (!e.touches || e.touches.length >= 2 || !this._moved) { return; }
+
+ // prevent touchEnd from firing twice
+ if (!this._zooming) { return; }
+ this._zooming = false;
- var zoom = this._map.getZoom() + Math.round(Math.log(this._scale)/Math.LN2),
+ var oldZoom = this._map.getZoom(),
+ zoom = this._map._limitZoom(oldZoom + Math.round(Math.log(this._scale)/Math.LN2)),
+ zoomDelta = zoom - oldZoom,
centerOffset = this._centerOffset.subtract(this._delta).divideBy(this._scale),
centerPoint = this._map.getPixelOrigin().add(this._startCenter).add(centerOffset),
center = this._map.unproject(centerPoint);
- this._map.setView(center, zoom, true);
-
- this._map._panes.popupPane.style.display = '';
-
- this._scale = null;
L.DomEvent.removeListener(document, 'touchmove', this._onTouchMove);
L.DomEvent.removeListener(document, 'touchend', this._onTouchEnd);
+
+ var finalScale = Math.pow(2, zoomDelta),
+ mapPaneOffset = L.DomUtil.getPosition(this._map._mapPane),
+ startTransform = L.DomUtil.getTranslateString(mapPaneOffset) + ' ' + this._map._tileBg.style.webkitTransform;
+
+ this._map._runAnimation(center, zoom, finalScale / this._scale, startTransform, this._startCenter.add(centerOffset));
}
});
View
@@ -290,15 +290,17 @@ L.Map = L.Class.extend({
this._mapPane = panes.mapPane = this._createPane('leaflet-map-pane', this._container);
- this._tilePane = panes.tilePane = this._createPane('leaflet-tile-pane');
+ this._tilePane = panes.tilePane = this._createPane('leaflet-tile-pane', this._mapPane);
+ this._objectsPane = panes.objectsPane = this._createPane('leaflet-objects-pane', this._mapPane);
+
panes.shadowPane = this._createPane('leaflet-shadow-pane');
panes.overlayPane = this._createPane('leaflet-overlay-pane');
panes.markerPane = this._createPane('leaflet-marker-pane');
panes.popupPane = this._createPane('leaflet-popup-pane');
},
_createPane: function(className, container) {
- return L.DomUtil.create('div', className, container || this._mapPane);
+ return L.DomUtil.create('div', className, container || this._objectsPane);
},
_resetView: function(center, zoom) {
@@ -14,48 +14,42 @@ L.Map.include(!(L.Transition && L.Transition.implemented()) ? {} : {
//if offset does not exceed half of the view
if (!this._offsetIsWithinView(offset, 1)) { return false; }
- this._initTilePanes();
- this._runAnimation(center, zoom, scale, offset);
+ this._prepareTileBg();
- return true;
- },
+ this._mapPane.className += ' leaflet-animating';
+
+ var mapPaneOffset = L.DomUtil.getPosition(this._mapPane),
+ centerPoint = this.containerPointToLayerPoint(this.getSize().divideBy(2)),
+ origin = centerPoint.add(offset),
+ startTransform = L.DomUtil.getTranslateString(mapPaneOffset);
- _initTilePanes: function() {
- if (!this._tileBg) {
- this._tileBg = this._createPane('leaflet-tile-pane');
- this._tileBg.style.zIndex = 1;
- }
-
- this._swapFrontAndBg(); //TODO refactor away tile layer swapping to share it with touch zoom
+ this._runAnimation(center, zoom, scale, startTransform, origin);
- if (!this._tileBg.transition) {
- this._tileBg.transition = new L.Transition(this._tileBg, {duration: 0.25, easing: 'cubic-bezier(0.25,0.1,0.25,0.75)'});
- this._tileBg.transition.on('end', this._onZoomTransitionEnd, this);
- }
+ return true;
},
- _runAnimation: function(center, zoom, scale, offset) {
- var mapPaneOffset = L.DomUtil.getPosition(this._mapPane),
- centerPoint = this.containerPointToLayerPoint(this.getSize().divideBy(2)),
- origin = centerPoint.add(offset).subtract(mapPaneOffset.divideBy(scale - 1));
-
- this._mapPane.className += ' leaflet-animating';
+
+ _runAnimation: function(center, zoom, scale, startTransform, origin) {
this._animatingZoom = true;
//load tiles in the main tile pane
this._resetView(center, zoom);
- this._tileBg.style[L.DomUtil.TRANSFORM_PROPERTY] = L.DomUtil.getTranslateString(mapPaneOffset);
-
- //TODO eliminate this ugly setTimeout hack
- setTimeout(L.Util.bind(function() {
- var options = {};
- options[L.DomUtil.TRANSFORM_PROPERTY] = L.DomUtil.getScaleString(scale, origin);
- this._tileBg.transition.run(options);
- }, this), 20);
+ this._tileBg.style[L.DomUtil.TRANSFORM_PROPERTY] = startTransform;
+
+ this._tileBg.offsetWidth; //hack to make sure transform is updated before running animation
+
+ var options = {};
+ options[L.DomUtil.TRANSFORM_PROPERTY] = startTransform + ' ' + L.DomUtil.getScaleString(scale, origin);
+ this._tileBg.transition.run(options);
},
- _swapFrontAndBg: function() {
+ _prepareTileBg: function() {
+ if (!this._tileBg) {
+ this._tileBg = this._createPane('leaflet-tile-pane', this._mapPane);
+ this._tileBg.style.zIndex = 1;
+ }
+
var oldTilePane = this._tilePane,
newTilePane = this._tileBg;
@@ -70,13 +64,23 @@ L.Map.include(!(L.Transition && L.Transition.implemented()) ? {} : {
this._tilePane = this._panes.tilePane = newTilePane;
this._tileBg = oldTilePane;
+
+ if (!this._tileBg.transition) {
+ this._tileBg.transition = new L.Transition(this._tileBg, {duration: 0.25, easing: 'cubic-bezier(0.25,0.1,0.25,0.75)'});
+ this._tileBg.transition.on('end', this._onZoomTransitionEnd, this);
+ }
},
_onZoomTransitionEnd: function() {
+ this._restoreTileFront();
+
+ this._mapPane.className = this._mapPane.className.replace(' leaflet-animating', ''); //TODO toggleClass util
+ this._animatingZoom = false;
+ },
+
+ _restoreTileFront: function() {
this._tilePane.style.visibility = '';
this._tilePane.style.zIndex = 2;
this._tileBg.style.zIndex = 1;
- this._mapPane.className = this._mapPane.className.replace(' leaflet-animating', ''); //TODO toggleClass util
- this._animatingZoom = false;
}
});

0 comments on commit 9d93998

Please sign in to comment.