1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
L.Map.include(!L.DomUtil.TRANSITION ? {} : {
_zoomToIfCenterInView: function(center, zoom, centerOffset) {
if (this._animatingZoom) { return true; }
if (!this.options.zoomAnimation) { return false; }
var zoomDelta = zoom - this._zoom,
scale = Math.pow(2, zoomDelta),
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';
var centerPoint = this.containerPointToLayerPoint(this.getSize().divideBy(2)),
origin = centerPoint.add(offset);
this._prepareTileBg();
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;
//dumb FireFox hack, I have no idea why this magic zero translate fixes the scale transition problem
if (L.Browser.gecko || window.opera) {
this._tileBg.style[transform] += ' translate(0,0)';
}
var scaleStr;
// Android 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) {
this._tileBg.style[transform + 'Origin'] = origin.x + 'px ' + origin.y + 'px';
scaleStr = 'scale(' + scale + ')';
} else {
scaleStr = L.DomUtil.getScaleString(scale, origin);
}
L.Util.falseFn(this._tileBg.offsetWidth); //hack to make sure transform is updated before running animation
var options = {};
options[transform] = this._tileBg.style[transform] + ' ' + scaleStr;
this._tileBg.transition.run(options);
},
_prepareTileBg: function() {
if (!this._tileBg) {
this._tileBg = this._createPane('leaflet-tile-pane', this._mapPane);
this._tileBg.style.zIndex = 1;
}
var tilePane = this._tilePane,
tileBg = this._tileBg;
// prepare the background pane to become the main tile pane
//tileBg.innerHTML = '';
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;
this._tileBg = tilePane;
if (!this._tileBg.transition) {
this._tileBg.transition = new L.Transition(this._tileBg, {duration: 0.3, easing: 'cubic-bezier(0.25,0.1,0.25,0.75)'});
this._tileBg.transition.on('end', this._onZoomTransitionEnd, this);
}
this._stopLoadingBgTiles();
},
// stops loading all tiles in the background layer
_stopLoadingBgTiles: function() {
var tiles = [].slice.call(this._tileBg.getElementsByTagName('img'));
for (var i = 0, len = tiles.length; i < len; i++) {
if (!tiles[i].complete) {
tiles[i].src = '';
tiles[i].parentNode.removeChild(tiles[i]);
}
}
},
_onZoomTransitionEnd: function() {
this._restoreTileFront();
L.Util.falseFn(this._tileBg.offsetWidth);
this._resetView(this._animateToCenter, this._animateToZoom, true);
//TODO clear tileBg on map layersload
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 = '';
}
}
});
|