|
@@ -10,7 +10,7 @@
|
10
|
10
|
layer: null,
|
11
|
11
|
features: null,
|
12
|
12
|
cache: null,
|
13
|
|
-
|
|
13
|
+
|
14
|
14
|
//
|
15
|
15
|
// Leaflet layer methods
|
16
|
16
|
//
|
|
@@ -21,33 +21,39 @@
|
21
|
21
|
this.cache = {};
|
22
|
22
|
L.GridLayer.prototype.initialize.call(this, options);
|
23
|
23
|
},
|
24
|
|
-
|
25
|
|
- createTile: function (coords) {
|
|
24
|
+
|
|
25
|
+ createTile(coords, done) {
|
26
|
26
|
var tile = L.DomUtil.create('div', 'leaflet-tile');
|
27
|
27
|
tile.style['box-shadow'] = 'inset 0 0 2px #f00';
|
28
|
28
|
var url = this._expandUrl(this.url, coords);
|
29
|
|
- if (this.cache[url]) {
|
30
|
|
- this._updateLayers(url, this.cache[url]);
|
|
29
|
+ if (this.cache[coords]) {
|
|
30
|
+ done.call(this);
|
31
|
31
|
} else {
|
32
|
|
- this._ajaxRequest('GET', url, false, this._updateLayers.bind(this, url));
|
|
32
|
+ this._ajaxRequest('GET', url, false, this._updateCache.bind(this, done, coords));
|
33
|
33
|
}
|
34
|
34
|
return tile;
|
35
|
35
|
},
|
36
|
|
-
|
|
36
|
+
|
37
|
37
|
onAdd(map) {
|
38
|
38
|
L.GridLayer.prototype.onAdd.call(this, map);
|
39
|
39
|
map.addLayer(this.layer);
|
40
|
40
|
this.map = map;
|
41
|
41
|
map.on('zoomanim', this._onZoomAnim.bind(this));
|
|
42
|
+ this.on('loading', this._onLoading.bind(this));
|
|
43
|
+ this.on('tileload', this._onTileLoad.bind(this));
|
|
44
|
+ this.on('tileunload', this._onTileUnLoad.bind(this));
|
42
|
45
|
},
|
43
|
|
-
|
|
46
|
+
|
44
|
47
|
onRemove(map) {
|
|
48
|
+ this.off('tileunload', this._onTileUnLoad.bind(this));
|
|
49
|
+ this.off('tileload', this._onTileLoad.bind(this));
|
|
50
|
+ this.off('loading', this._onLoading.bind(this));
|
45
|
51
|
map.off('zoomanim', this._onZoomAnim.bind(this));
|
46
|
52
|
this.map = null;
|
47
|
53
|
map.removeLayer(this.layer)
|
48
|
54
|
L.GridLayer.prototype.onRemove.call(this, map);
|
49
|
55
|
},
|
50
|
|
-
|
|
56
|
+
|
51
|
57
|
//
|
52
|
58
|
// Custom methods
|
53
|
59
|
//
|
|
@@ -80,23 +86,53 @@
|
80
|
86
|
});
|
81
|
87
|
return L.Util.template(template, coords);
|
82
|
88
|
},
|
83
|
|
-
|
84
|
|
- _updateLayers: function(url, geoData) {
|
|
89
|
+
|
|
90
|
+ _hashCode: function(str) {
|
|
91
|
+ var hash = 0, i, chr;
|
|
92
|
+ if (str.length === 0) return hash;
|
|
93
|
+ for (i = 0; i < str.length; i++) {
|
|
94
|
+ chr = str.charCodeAt(i);
|
|
95
|
+ hash = ((hash << 5) - hash) + chr;
|
|
96
|
+ hash |= 0; // Convert to 32bit integer
|
|
97
|
+ }
|
|
98
|
+ return hash;
|
|
99
|
+ },
|
|
100
|
+
|
|
101
|
+ _updateTiles: function() {
|
|
102
|
+ this.layer.clearLayers();
|
|
103
|
+ this.features = {};
|
|
104
|
+ for (var coords in this.cache) {
|
|
105
|
+ if (this.cache.hasOwnProperty(coords)) {
|
|
106
|
+ this._drawTile(coords);
|
|
107
|
+ }
|
|
108
|
+ }
|
|
109
|
+ },
|
|
110
|
+
|
|
111
|
+ _drawTile(coords) {
|
|
112
|
+ var geoData = this.cache[coords];
|
85
|
113
|
if (geoData.type == 'FeatureCollection'){
|
86
|
114
|
geoData = geoData.features;
|
87
|
115
|
}
|
88
|
116
|
for (var i=0;i<geoData.length;i++) {
|
|
117
|
+ if (!geoData[i].id) {
|
|
118
|
+ geoData[i].id = this._hashCode(JSON.stringify(geoData[i].geometry));
|
|
119
|
+ }
|
89
|
120
|
var id = geoData[i].id;
|
90
|
121
|
if (!this.features[id]) {
|
91
|
122
|
this.layer.addData(geoData[i]);
|
92
|
123
|
this.features[id] = true;
|
93
|
124
|
}
|
94
|
125
|
}
|
95
|
|
- if (!this.cache[url]) {
|
96
|
|
- this.cache[url] = geoData;
|
|
126
|
+ if (!this.cache[coords]) {
|
|
127
|
+ this.cache[coords] = geoData;
|
97
|
128
|
}
|
98
|
129
|
},
|
99
|
|
-
|
|
130
|
+
|
|
131
|
+ _updateCache: function(done, coords, geoData) {
|
|
132
|
+ this.cache[coords] = geoData;
|
|
133
|
+ done.call(this);
|
|
134
|
+ },
|
|
135
|
+
|
100
|
136
|
_ajaxRequest: function(method, url, data, callback) {
|
101
|
137
|
var request = new XMLHttpRequest();
|
102
|
138
|
request.open(method, url, true);
|
|
@@ -113,16 +149,32 @@
|
113
|
149
|
}
|
114
|
150
|
return request;
|
115
|
151
|
},
|
116
|
|
-
|
|
152
|
+
|
117
|
153
|
_onZoomAnim: function (e) {
|
118
|
154
|
var zoom = e.zoom;
|
119
|
155
|
if ((this.options.maxZoom && zoom > this.options.maxZoom) ||
|
120
|
156
|
(this.options.minZoom && zoom < this.options.minZoom)) {
|
121
|
157
|
this.map.removeLayer(this.layer);
|
|
158
|
+ this.cache = {};
|
|
159
|
+ this.layer.clearLayers();
|
122
|
160
|
} else {
|
|
161
|
+ this._updateTiles();
|
123
|
162
|
this.map.addLayer(this.layer);
|
124
|
163
|
}
|
125
|
|
- }
|
|
164
|
+ },
|
|
165
|
+
|
|
166
|
+ _onLoading: function (e) {
|
|
167
|
+ this._updateTiles();
|
|
168
|
+ },
|
|
169
|
+
|
|
170
|
+ _onTileLoad: function (e) {
|
|
171
|
+ this._drawTile(e.coords);
|
|
172
|
+ },
|
|
173
|
+
|
|
174
|
+ _onTileUnLoad: function (e) {
|
|
175
|
+ delete this.cache[e.coords]
|
|
176
|
+ },
|
|
177
|
+
|
126
|
178
|
});
|
127
|
179
|
|
128
|
180
|
L.geoJSONTileLayer = function (url, options) {
|