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: '© <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: '© <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.

0 comments :
Post a Comment