Thursday, March 3, 2016

Esri Leaflet Dynamic TileLayer Plugin Example

While working in one my Esri-Leaflet based application, I am stumbled on rendering dynamic map layers on tiled basis. Esri leaflet-api does the perfect job on non-tiled layer display but L.esri.DynamicMapLayer, doesn’t provide the tiled dynamic map layers. Looking around I came across the Tiled dynamic layer plugin for esri-leaflet, for displaying the DynamicMapLayer in tiled mode.

Here I have created both non-tiled and tiled DynamicMapLayer version for comparison using plain esri-leaflet and esri-leaflet with plugin.


1:  <!DOCTYPE html>  
2:  <html>  
3:  <head>  
4:    <title>ESRI Leaflet Dynamic Map Layer With Map Tiles</title>  
5:    <meta charset="utf-8" />  
6:    <link   
7:      rel="stylesheet"   
8:      href="http://cdn.leafletjs.com/leaflet-0.7/leaflet.css"  
9:    />  
10:  </head>  
11:  <body>  
12:    <div id="map-non-tiled" style="width: 600px; height: 400px"></div>  
13:    <div id="map-tiled" style="width: 600px; height: 400px"></div>  
14:    
15:  <script src="//cdn.jsdelivr.net/leaflet/0.7.3/leaflet.js"></script>  
16:  <script src="//cdn.jsdelivr.net/leaflet.esri/1.0.0-rc.7/esri-leaflet.js"></script>  
17:     
18:  <script>  
19:  (function (factory) {  
20:   //define an AMD module that relies on 'leaflet'  
21:   if (typeof define === 'function' && define.amd) {  
22:    define(['leaflet', 'esri-leaflet'], function (L, EsriLeaflet) {  
23:     return factory(L, EsriLeaflet);  
24:    });  
25:   //define a common js module that relies on 'leaflet'  
26:   } else if (typeof module === 'object' && typeof module.exports === 'object') {  
27:    module.exports = factory(require('leaflet'), require('esri-leaflet'));  
28:   }  
29:    
30:   if(typeof window !== 'undefined' && window.L){  
31:    factory(window.L, L.esri);  
32:   }  
33:  }(function (L, EsriLeaflet) {  
34:    
35:  EsriLeaflet.Layers.TiledDynamicMapLayer = L.TileLayer.extend({  
36:    
37:   options: L.Util.extend({}, EsriLeaflet.Layers.DynamicMapLayer.prototype.options),  
38:    
39:   _requests: [],  
40:    
41:   /**  
42:    * @constructor  
43:    * @extends {L.TileLayer}  
44:    * @param {String} url  
45:    * @param {Object} options  
46:    */  
47:   initialize: function(url, options) {  
48:    L.TileLayer.prototype.initialize.call(this, url, options);  
49:    EsriLeaflet.DynamicMapLayer.prototype.initialize.call(this, url, options);  
50:   },  
51:    
52:   /**  
53:    * @param {L.Map} map  
54:    */  
55:   onAdd: function(map) {  
56:    if (map.options.crs && map.options.crs.code) {  
57:     var sr = map.options.crs.code.split(':')[1];  
58:     this.options.bboxSR = sr;  
59:     this.options.imageSR = sr;  
60:    }  
61:    
62:    map.on('zoomstart zoomend', this._onZoomChange, this);  
63:    return L.TileLayer.prototype.onAdd.call(this, map);  
64:   },  
65:    
66:   /**  
67:    * @param {L.Map} map  
68:    */  
69:   onRemove: function(map) {  
70:    map.off('zoomstart zoomend', this._onZoomChange, this);  
71:    L.TileLayer.prototype.onRemove.call(this, map);  
72:    },  
73:    
74:   /**  
75:    * @param {Array.<Number>|Array.<String>} layers  
76:    * @return {L.esri.Layers.TiledDynamicMapLayer} self  
77:    */  
78:   setLayers: function(layers) {  
79:    this._reset();  
80:    return EsriLeaflet.Layers.DynamicMapLayer.prototype.setLayers.call(this, layers);  
81:   },  
82:    
83:   /**  
84:    * @param {Array.<Object>} layerDefs  
85:    * @return {L.esri.Layers.TiledDynamicMapLayer} self  
86:    */  
87:   setLayerDefs: function(layerDefs) {  
88:    this._reset();  
89:    return EsriLeaflet.Layers.DynamicMapLayer.prototype.setLayerDefs.call(this, layerDefs);  
90:   },  
91:    
92:   /**  
93:    * @param {Object} timeOptions  
94:    * @return {L.esri.Layers.TiledDynamicMapLayer} self  
95:    */  
96:   setTimeOptions: function(timeOptions) {  
97:    this._reset();  
98:    return EsriLeaflet.Layers.DynamicMapLayer.prototype.setTimeOptions.call(this, timeOptions);  
99:   },  
100:    
101:   /**  
102:    * Set/unset zooming flag to avoid unneeded requests  
103:    * @param {Object} e  
104:    */  
105:   _onZoomChange: function(e) {  
106:    this._zooming = (e.type === 'zoomstart');  
107:   },  
108:    
109:   /**  
110:    * @param {L.LatLngBounds} bounds  
111:    * @param {L.Point}    size  
112:    * @return {Object}  
113:    */  
114:   _buildExportParams: function(bounds, size) {  
115:    var ne = this._map.options.crs.project(bounds._northEast);  
116:    var sw = this._map.options.crs.project(bounds._southWest);  
117:    
118:    //ensure that we don't ask ArcGIS Server for a taller image than we have actual map displaying  
119:    var top = this._map.latLngToLayerPoint(bounds._northEast);  
120:    var bottom = this._map.latLngToLayerPoint(bounds._southWest);  
121:    
122:    if (top.y > 0 || bottom.y < size.y) {  
123:     size.y = bottom.y - top.y;  
124:    }  
125:    
126:    var params = {  
127:     bbox: [sw.x, sw.y, ne.x, ne.y].join(','),  
128:     size: size.x + ',' + size.y,  
129:     dpi: 96,  
130:     format: this.options.format,  
131:     transparent: this.options.transparent,  
132:     bboxSR: this.options.bboxSR,  
133:     imageSR: this.options.imageSR  
134:    };  
135:    
136:    if (this.options.layers) {  
137:     params.layers = 'show:' + this.options.layers.join(',');  
138:    }  
139:    
140:    if (this.options.layerDefs) {  
141:     params.layerDefs = JSON.stringify(this.options.layerDefs);  
142:    }  
143:    
144:    if (this.options.timeOptions) {  
145:     params.timeOptions = JSON.stringify(this.options.timeOptions);  
146:    }  
147:    
148:    if (this.options.from && this.options.to) {  
149:     params.time = this.options.from.valueOf() + ',' + this.options.to.valueOf();  
150:    }  
151:    
152:    if (this._service.options.token) {  
153:     params.token = this._service.options.token;  
154:    }  
155:    
156:    return params;  
157:   },  
158:    
159:   /**  
160:    * @param {Object} tile  
161:    * @param {L.Point} tilePoint  
162:    */  
163:   _loadTile: function(tile, tilePoint) {  
164:    tile._layer = this;  
165:    tile.onload = this._tileOnLoad;  
166:    tile.onerror = this._tileOnError;  
167:    
168:    this._adjustTilePoint(tilePoint);  
169:    this.getTileUrl(tilePoint, function(err, url) {  
170:     tile.src = url;  
171:    });  
172:    
173:    this.fire('tileloadstart', {  
174:     tile: tile  
175:    });  
176:   },  
177:    
178:   /**  
179:    * Async request tile url  
180:    * @param {L.Point} tilePoint  
181:    * @param {Function} callback  
182:    */  
183:   getTileUrl: function(tilePoint, callback) { // (Point, Number) -> String  
184:    
185:    var map = this._map,  
186:     tileSize = this.options.tileSize,  
187:    
188:     nwPoint = tilePoint.multiplyBy(tileSize),  
189:     sePoint = nwPoint.add([tileSize, tileSize]);  
190:    
191:    var bounds = new L.LatLngBounds(map.unproject(nwPoint, tilePoint.z),  
192:     map.unproject(sePoint, tilePoint.z));  
193:    var size = new L.Point(this.options.tileSize, this.options.tileSize);  
194:    
195:    var params = this._buildExportParams(bounds, size);  
196:    this._requestExport(params, bounds, callback);  
197:   },  
198:    
199:   /**  
200:    * Export call, json or image straight awy  
201:    * @param {Object}     params  
202:    * @param {L.LatLngBounds} bounds  
203:    * @param {Function}    callback  
204:    */  
205:   _requestExport: function(params, bounds, callback) {  
206:    if (this.options.f === 'json') {  
207:     this._requests.push(this._service.get('export', params, function(error, response) {  
208:      callback(null, response.href, bounds);  
209:     }, this));  
210:    } else {  
211:     params.f = 'image';  
212:     callback(null, this.options.url + 'export' + L.Util.getParamString(params), bounds);  
213:    }  
214:   },  
215:    
216:   /**  
217:    * Bounds or params changed  
218:    */  
219:   _update: function() {  
220:    if (this._map && this._map._animatingZoom) {  
221:     return;  
222:    }  
223:    L.TileLayer.prototype._update.call(this);  
224:   }  
225:    
226:  });  
227:    
228:  (function(methods) {  
229:   for (var i = 0, len = methods.length; i < len; i++) {  
230:    EsriLeaflet.Layers.TiledDynamicMapLayer.prototype[methods[i]] =  
231:     EsriLeaflet.Layers.DynamicMapLayer.prototype[methods[i]];  
232:   }  
233:  })([  
234:   /** @borrows L.esri.Layers.DynamicMapLayer.prototype.getLayers as getLayers */  
235:   'getLayers',  
236:   /** @borrows L.esri.Layers.DynamicMapLayer.prototype.getLayerDefs as getLayerDefs */  
237:   'getLayerDefs',  
238:   /** @borrows L.esri.Layers.DynamicMapLayer.prototype.getTimeOptions as getTimeOptions */  
239:   'getTimeOptions',  
240:   /** @borrows L.esri.Layers.DynamicMapLayer.prototype.metadata as metadata */  
241:   'metadata',  
242:   /** @borrows L.esri.Layers.DynamicMapLayer.prototype.query as query */  
243:   'query',  
244:   /** @borrows L.esri.Layers.DynamicMapLayer.prototype.identify as identify */  
245:   'identify',  
246:   /** @borrows L.esri.Layers.DynamicMapLayer.prototype.find as find */  
247:   'find',  
248:   /** @borrows L.esri.Layers.DynamicMapLayer.prototype._getPopupData as _getPopupData */  
249:   '_getPopupData',  
250:   /** @borrows L.esri.Layers.DynamicMapLayer.prototype._propagateEvent as _propagateEvent */  
251:   '_propagateEvent'  
252:  ]);  
253:    
254:  // factory  
255:  EsriLeaflet.tiledDynamicMapLayer = function(url, options) {  
256:   return new EsriLeaflet.Layers.TiledDynamicMapLayer(url, options);  
257:  };  
258:    
259:    
260:   return EsriLeaflet;  
261:  }));  
262:  //# sourceMappingURL=esri-leaflet-dynamic-tilelayer-src.js.map  
263:    
264:  </script>  
265:    
266:    
267:    
268:    
269:  <script>  
270:         
271:  var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';  
272:           
273:  // create map1  
274:  var map1 = new L.Map('map-non-tiled');  
275:  L.tileLayer(osmUrl, {  
276:    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'  
277:  }).addTo(map1);  
278:  // set the map1's starting view  
279:  map1.setView( new L.LatLng(39.828328,-98.57941), 4 );  
280:    
281:    
282:  // create map2  
283:  var map2 = new L.Map('map-tiled');  
284:  L.tileLayer(osmUrl, {  
285:    attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'  
286:  }).addTo(map2);  
287:    
288:  // set the map2's starting view  
289:  map2.setView( new L.LatLng(39.828328,-98.57941), 4 );   
290:     
291:   var urlLayer = "//server.arcgisonline.com/ArcGIS/rest/services/Specialty/Soil_Survey_Map/MapServer";  
292:   var layer1 =L.esri.dynamicMapLayer(urlLayer,{  
293:     layers:0,  
294:     bboxSR:102100,  
295:     imageSR:102100,       
296:     format:'png24',  
297:     transparent:true,  
298:     f:'image',  
299:     tiled:true,  
300:     zoom:8  
301:   });  
302:     
303:   var layer2 = L.esri.tiledDynamicMapLayer(urlLayer,{  
304:     layers:0,  
305:     bboxSR:102100,  
306:     imageSR:102100,    
307:     format:'png24',  
308:     transparent:true,  
309:     f:'image',  
310:     tiled:true,  
311:     zoom:8  
312:   });  
313:     
314:   layer1.addTo(map1);  
315:   layer2.addTo(map2);   
316:    </script>  
317:  </body>  
318:  </html>  
319:    

Hope some will find this helpful in the future.

esri-leaflet , Leaflet , WMS

0 comments :

Post a Comment

 

© 2011 GIS and Remote Sensing Tools, Tips and more .. ToS | Privacy Policy | Sitemap

About Me