/**
@module L.PtvLayer
**/
L.PtvLayer = L.PtvLayer || {};
/**
Provides the PTV AbstractOverlay Layer class.
@class L.PtvLayer.AbstractOverlay
@extends L.ILayer
@params {Object} options The options object
@params {String} [options.format] The image format used in tile requests.
@params {String} [options.beforeSend] Function to be called before sending the request with the request object given as first parameter. The (modified) request object must be returned.
@constructor
**/
L.PtvLayer.AbstractOverlay = L.Class.extend({
includes: L.Mixin.Events,
_el1: null,
_el2: null,
_elCur: 0,
_client: null,
_map: null,
_requestObject: null,
/**
Default options used in this class.
@property options
@type Object
**/
options: {
/**
The image format used in tile requests.
@property options.format
@type String
@default "PNG"
**/
format: 'PNG',
/**
Function to be called before sending the request with the request object given as first parameter. The (modified) request object must be returned.
@property options.beforeSend
@type function
@default null
**/
beforeSend: null,
/**
The world bounds for PTV Maps.
@property options.bounds
@type L.LatLngBounds
@default [[85.0, -178.965000], [-66.5, 178.965000]]
**/
bounds: new L.LatLngBounds([[85.0, -178.965000], [-66.5, 178.965000]])
},
/**
Constructor
@method L.PtvLayer.AbstractOverlay
@param {XMapClient} client optional XMapClient object
@param {Object} options optional options object
**/
initialize: function(client, options) {
this._client = client;
if (typeof client !== 'object' ) {
if (typeof XMapClient !== 'function') {
throw Error('The XMapClient object is not accessible globally. Have you loaded "xmap-client.js" properly?');
} else {
this._client = new XMapClient(null, 1);
}
}
L.Util.setOptions(this, options);
},
onAdd: function(map) {
this._map = map;
// create a DOM element and put it into one of the map panes
this._el1 = L.DomUtil.create('img', 'leaflet-tile leaflet-zoom-hide');
this._el2 = L.DomUtil.create('img', 'leaflet-tile leaflet-zoom-hide');
this._el1.style.cssText = '-webkit-transition: none; -moz-transition: none; -o-transition: opacity 0 linear; transition: none;';
this._el2.style.cssText = '-webkit-transition: none; -moz-transition: none; -o-transition: opacity 0 linear; transition: none;';
this._el1.onload = (function(self, el) { return function() { self._setActiveEl.call(self, el); }; })(this, this._el1);
this._el2.onload = (function(self, el) { return function() { self._setActiveEl.call(self, el); }; })(this, this._el2);
map.getPanes().overlayPane.appendChild(this._el1);
map.getPanes().overlayPane.appendChild(this._el2);
map.on({
'moveend': this._update
}, this);
this._update();
},
onRemove: function(map) {
map.off({
'moveend': this._update
}, this);
map.getPanes().overlayPane.removeChild(this._el1);
map.getPanes().overlayPane.removeChild(this._el2);
},
_setActiveEl: function(el) {
if(el === this._el1) {
L.DomUtil.addClass(this._el1, 'leaflet-tile-loaded');
L.DomUtil.removeClass(this._el2, 'leaflet-tile-loaded');
} else {
L.DomUtil.addClass(this._el2, 'leaflet-tile-loaded');
L.DomUtil.removeClass(this._el1, 'leaflet-tile-loaded');
}
},
_update: function() {
var bounds = this._map.getBounds(), mapSize = this._map.getSize(), el = (!this._elCur ? this._el1 : this._el2);
this._elCur = (this._elCur + 1) % 2;
if (this._map.getZoom() > this._map.getMaxZoom() || this._map.getZoom() < this._map.getMinZoom()) {
return;
}
if (this.options.bounds) {
bounds.clip(this.options.bounds);
}
if ( typeof this._client.cancelPendingRequests === 'function') {
this._client.cancelPendingRequests();
}
var se = this._map.project(bounds.getSouthEast()), nw = this._map.project(bounds.getNorthWest());
mapSize.x = Math.max(256, se.x - nw.x);
mapSize.y = Math.max(256, se.y - nw.y);
var tileUrl = this._requestTile(bounds, mapSize, el);
var pos = this._map.latLngToLayerPoint(bounds.getNorthWest());
L.DomUtil.setPosition(el, pos, false);
},
_getRequestObject: function() {
return {
mapSection: {
leftTop: {
"$type": "Point",
point: {
"$type": "PlainPoint",
x: 0,
y: 0
}
},
rightBottom: {
"$type": "Point",
point: {
"$type": "PlainPoint",
x: 0,
y: 0
}
}
},
mapParams: {
showScale: false,
useMiles: false
},
imageInfo: {
format: '',
width: 0,
height: 0
},
layers: [],
includeImageInResponse: true,
callerContext: {
properties: [{
key: "Profile",
value: ""
}, {
"key": "CoordFormat",
"value": "OG_GEODECIMAL"
}]
}
};
},
_requestTile: function(bounds, mapSize, el) {
var self = this, map = this._map, crs = map.options.crs, nw = crs.project(bounds.getNorthWest()), se = crs.project(bounds.getSouthEast()), bbox = new L.LatLngBounds([se.y, nw.x], [nw.y, se.x]);
var req = this._getRequestObject();
req.mapSection.leftTop.point.x = bbox.getNorthWest().lng;
req.mapSection.leftTop.point.y = bbox.getNorthWest().lat;
req.mapSection.rightBottom.point.x = bbox.getSouthEast().lng;
req.mapSection.rightBottom.point.y = bbox.getSouthEast().lat;
req.imageInfo.format = this.options.format;
req.imageInfo.width = mapSize.x;
req.imageInfo.height = mapSize.y;
if (typeof this.options.beforeSend === "function") {
req = this.options.beforeSend(req);
}
this._client.renderMapBoundingBox(req.mapSection, req.mapParams, req.imageInfo, req.layers, req.includeImageInResponse, req.callerContext, (function(el) {
return function(resp, error) {
self._renderMapCallback.call(self, resp, error, el);
};
})(el));
this.fire('loading');
},
_renderMapCallback: function(resp, error, el) {
if (!error) {
el.src = L.PtvUtils.createDataURI(resp.image.rawImage);
} else {
el.src = L.Util.emptyImageUrl;
console.log(error.errorMessage);
}
this.fire('load', {
tile: el,
url: el.src
});
}
});