322 lines
12 KiB
Vue
322 lines
12 KiB
Vue
|
|
||
|
/**
|
||
|
* @requires SuperMap/Layer.js
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Class: SuperMap.Layer.FixedZoomLevels
|
||
|
* Some Layers will already have established zoom levels (like google
|
||
|
* or ve). Instead of trying to determine them and populate a resolutions[]
|
||
|
* Array with those values, we will hijack the resolution functionality
|
||
|
* here.
|
||
|
*
|
||
|
* When you subclass FixedZoomLevels:
|
||
|
*
|
||
|
* The initResolutions() call gets nullified, meaning no resolutions[] array
|
||
|
* is set up. Which would be a big problem getResolution() in Layer, since
|
||
|
* it merely takes map.zoom and indexes into resolutions[]... but....
|
||
|
*
|
||
|
* The getResolution() call is also overridden. Instead of using the
|
||
|
* resolutions[] array, we simply calculate the current resolution based
|
||
|
* on the current extent and the current map size. But how will we be able
|
||
|
* to calculate the current extent without knowing the resolution...?
|
||
|
*
|
||
|
* The getExtent() function is also overridden. Instead of calculating extent
|
||
|
* based on the center point and the current resolution, we instead
|
||
|
* calculate the extent by getting the lonlats at the top-left and
|
||
|
* bottom-right by using the getLonLatFromViewPortPx() translation function,
|
||
|
* taken from the pixel locations (0,0) and the size of the map. But how
|
||
|
* will we be able to do lonlat-px translation without resolution....?
|
||
|
*
|
||
|
* The getZoomForResolution() method is overridden. Instead of indexing into
|
||
|
* the resolutions[] array, we call SuperMap.Layer.getExent(), passing in
|
||
|
* the desired resolution. With this extent, we then call getZoomForExtent()
|
||
|
*
|
||
|
*
|
||
|
* Whenever you implement a layer using SuperMap.Layer.FixedZoomLevels,
|
||
|
* it is your responsibility to provide the following three functions:
|
||
|
*
|
||
|
* - getLonLatFromViewPortPx
|
||
|
* - getViewPortPxFromLonLat
|
||
|
* - getZoomForExtent
|
||
|
*
|
||
|
* ...those three functions should generally be provided by any reasonable
|
||
|
* API that you might be working from.
|
||
|
*
|
||
|
*/
|
||
|
SuperMap.Layer.FixedZoomLevels = SuperMap.Class({
|
||
|
|
||
|
/********************************************************/
|
||
|
/* */
|
||
|
/* Baselayer Functions */
|
||
|
/* */
|
||
|
/* The following functions must all be implemented */
|
||
|
/* by all base layers */
|
||
|
/* */
|
||
|
/********************************************************/
|
||
|
|
||
|
/**
|
||
|
* Constructor: SuperMap.Layer.FixedZoomLevels
|
||
|
* Create a new fixed zoom levels layer.
|
||
|
*/
|
||
|
initialize: function() {
|
||
|
//this class is only just to add the following functions...
|
||
|
// nothing to actually do here... but it is probably a good
|
||
|
// idea to have layers that use these functions call this
|
||
|
// inititalize() anyways, in case at some point we decide we
|
||
|
// do want to put some functionality or state in here.
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Method: initResolutions
|
||
|
* Populate the resolutions array
|
||
|
*/
|
||
|
initResolutions: function() {
|
||
|
|
||
|
var props = new Array('minZoomLevel', 'maxZoomLevel', 'numZoomLevels');
|
||
|
|
||
|
for(var i=0, len=props.length; i<len; i++) {
|
||
|
var property = props[i];
|
||
|
this[property] = (this.options[property] != null)
|
||
|
? this.options[property]
|
||
|
: this.map[property];
|
||
|
}
|
||
|
|
||
|
if ( (this.minZoomLevel == null) ||
|
||
|
(this.minZoomLevel < this.MIN_ZOOM_LEVEL) ){
|
||
|
this.minZoomLevel = this.MIN_ZOOM_LEVEL;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// At this point, we know what the minimum desired zoom level is, and
|
||
|
// we must calculate the total number of zoom levels.
|
||
|
//
|
||
|
// Because we allow for the setting of either the 'numZoomLevels'
|
||
|
// or the 'maxZoomLevel' properties... on either the layer or the
|
||
|
// map, we have to define some rules to see which we take into
|
||
|
// account first in this calculation.
|
||
|
//
|
||
|
// The following is the precedence list for these properties:
|
||
|
//
|
||
|
// (1) numZoomLevels set on layer
|
||
|
// (2) maxZoomLevel set on layer
|
||
|
// (3) numZoomLevels set on map
|
||
|
// (4) maxZoomLevel set on map*
|
||
|
// (5) none of the above*
|
||
|
//
|
||
|
// *Note that options (4) and (5) are only possible if the user
|
||
|
// _explicitly_ sets the 'numZoomLevels' property on the map to
|
||
|
// null, since it is set by default to 16.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Note to future: In 3.0, I think we should remove the default
|
||
|
// value of 16 for map.numZoomLevels. Rather, I think that value
|
||
|
// should be set as a default on the Layer.WMS class. If someone
|
||
|
// creates a 3rd party layer and does not specify any 'minZoomLevel',
|
||
|
// 'maxZoomLevel', or 'numZoomLevels', and has not explicitly
|
||
|
// specified any of those on the map object either.. then I think
|
||
|
// it is fair to say that s/he wants all the zoom levels available.
|
||
|
//
|
||
|
// By making map.numZoomLevels *null* by default, that will be the
|
||
|
// case. As it is, I don't feel comfortable changing that right now
|
||
|
// as it would be a glaring API change and actually would probably
|
||
|
// break many peoples' codes.
|
||
|
//
|
||
|
|
||
|
//the number of zoom levels we'd like to have.
|
||
|
var desiredZoomLevels;
|
||
|
|
||
|
//this is the maximum number of zoom levels the layer will allow,
|
||
|
// given the specified starting minimum zoom level.
|
||
|
var limitZoomLevels = this.MAX_ZOOM_LEVEL - this.minZoomLevel + 1;
|
||
|
|
||
|
if ( ((this.options.numZoomLevels == null) &&
|
||
|
(this.options.maxZoomLevel != null)) // (2)
|
||
|
||
|
||
|
((this.numZoomLevels == null) &&
|
||
|
(this.maxZoomLevel != null)) // (4)
|
||
|
) {
|
||
|
//calculate based on specified maxZoomLevel (on layer or map)
|
||
|
desiredZoomLevels = this.maxZoomLevel - this.minZoomLevel + 1;
|
||
|
} else {
|
||
|
//calculate based on specified numZoomLevels (on layer or map)
|
||
|
// this covers cases (1) and (3)
|
||
|
desiredZoomLevels = this.numZoomLevels;
|
||
|
}
|
||
|
|
||
|
if (desiredZoomLevels != null) {
|
||
|
//Now that we know what we would *like* the number of zoom levels
|
||
|
// to be, based on layer or map options, we have to make sure that
|
||
|
// it does not conflict with the actual limit, as specified by
|
||
|
// the constants on the layer itself (and calculated into the
|
||
|
// 'limitZoomLevels' variable).
|
||
|
this.numZoomLevels = Math.min(desiredZoomLevels, limitZoomLevels);
|
||
|
} else {
|
||
|
// case (5) -- neither 'numZoomLevels' not 'maxZoomLevel' was
|
||
|
// set on either the layer or the map. So we just use the
|
||
|
// maximum limit as calculated by the layer's constants.
|
||
|
this.numZoomLevels = limitZoomLevels;
|
||
|
}
|
||
|
|
||
|
//now that the 'numZoomLevels' is appropriately, safely set,
|
||
|
// we go back and re-calculate the 'maxZoomLevel'.
|
||
|
this.maxZoomLevel = this.minZoomLevel + this.numZoomLevels - 1;
|
||
|
|
||
|
if (this.RESOLUTIONS != null) {
|
||
|
var resolutionsIndex = 0;
|
||
|
this.resolutions = [];
|
||
|
for(var i= this.minZoomLevel; i <= this.maxZoomLevel; i++) {
|
||
|
this.resolutions[resolutionsIndex++] = this.RESOLUTIONS[i];
|
||
|
}
|
||
|
this.maxResolution = this.resolutions[0];
|
||
|
this.minResolution = this.resolutions[this.resolutions.length - 1];
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* APIMethod: getResolution
|
||
|
* Get the current map resolution
|
||
|
*
|
||
|
* Returns:
|
||
|
* {Float} Map units per Pixel
|
||
|
*/
|
||
|
getResolution: function() {
|
||
|
|
||
|
if (this.resolutions != null) {
|
||
|
return SuperMap.Layer.prototype.getResolution.apply(this, arguments);
|
||
|
} else {
|
||
|
var resolution = null;
|
||
|
|
||
|
var viewSize = this.map.getSize();
|
||
|
var extent = this.getExtent();
|
||
|
|
||
|
if ((viewSize != null) && (extent != null)) {
|
||
|
resolution = Math.max( extent.getWidth() / viewSize.w,
|
||
|
extent.getHeight() / viewSize.h );
|
||
|
}
|
||
|
return resolution;
|
||
|
}
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* APIMethod: getExtent
|
||
|
* Calculates using px-> lonlat translation functions on tl and br
|
||
|
* corners of viewport
|
||
|
*
|
||
|
* Returns:
|
||
|
* {<SuperMap.Bounds>} A Bounds object which represents the lon/lat
|
||
|
* bounds of the current viewPort.
|
||
|
*/
|
||
|
getExtent: function () {
|
||
|
var extent = null;
|
||
|
|
||
|
|
||
|
var size = this.map.getSize();
|
||
|
|
||
|
var tlPx = new SuperMap.Pixel(0,0);
|
||
|
var tlLL = this.getLonLatFromViewPortPx(tlPx);
|
||
|
|
||
|
var brPx = new SuperMap.Pixel(size.w, size.h);
|
||
|
var brLL = this.getLonLatFromViewPortPx(brPx);
|
||
|
|
||
|
if ((tlLL != null) && (brLL != null)) {
|
||
|
extent = new SuperMap.Bounds(tlLL.lon,
|
||
|
brLL.lat,
|
||
|
brLL.lon,
|
||
|
tlLL.lat);
|
||
|
}
|
||
|
|
||
|
return extent;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Method: getZoomForResolution
|
||
|
* Get the zoom level for a given resolution
|
||
|
*
|
||
|
* Parameters:
|
||
|
* resolution - {Float}
|
||
|
*
|
||
|
* Returns:
|
||
|
* {Integer} A suitable zoom level for the specified resolution.
|
||
|
* If no baselayer is set, returns null.
|
||
|
*/
|
||
|
getZoomForResolution: function(resolution) {
|
||
|
|
||
|
if (this.resolutions != null) {
|
||
|
return SuperMap.Layer.prototype.getZoomForResolution.apply(this, arguments);
|
||
|
} else {
|
||
|
var extent = SuperMap.Layer.prototype.getExtent.apply(this, []);
|
||
|
return this.getZoomForExtent(extent);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/********************************************************/
|
||
|
/* */
|
||
|
/* Translation Functions */
|
||
|
/* */
|
||
|
/* The following functions translate GMaps and OL */
|
||
|
/* formats for Pixel, LonLat, Bounds, and Zoom */
|
||
|
/* */
|
||
|
/********************************************************/
|
||
|
|
||
|
|
||
|
//
|
||
|
// TRANSLATION: MapObject Zoom <-> SuperMap Zoom
|
||
|
//
|
||
|
|
||
|
/**
|
||
|
* Method: getOLZoomFromMapObjectZoom
|
||
|
* Get the OL zoom index from the map object zoom level
|
||
|
*
|
||
|
* Parameters:
|
||
|
* moZoom - {Integer}
|
||
|
*
|
||
|
* Returns:
|
||
|
* {Integer} An SuperMap Zoom level, translated from the passed in zoom
|
||
|
* Returns null if null value is passed in
|
||
|
*/
|
||
|
getOLZoomFromMapObjectZoom: function(moZoom) {
|
||
|
var zoom = null;
|
||
|
if (moZoom != null) {
|
||
|
zoom = moZoom - this.minZoomLevel;
|
||
|
if (this.map.baseLayer !== this) {
|
||
|
zoom = this.map.baseLayer.getZoomForResolution(
|
||
|
this.getResolutionForZoom(zoom)
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
return zoom;
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Method: getMapObjectZoomFromOLZoom
|
||
|
* Get the map object zoom level from the OL zoom level
|
||
|
*
|
||
|
* Parameters:
|
||
|
* olZoom - {Integer}
|
||
|
*
|
||
|
* Returns:
|
||
|
* {Integer} A MapObject level, translated from the passed in olZoom
|
||
|
* Returns null if null value is passed in
|
||
|
*/
|
||
|
getMapObjectZoomFromOLZoom: function(olZoom) {
|
||
|
var zoom = null;
|
||
|
if (olZoom != null) {
|
||
|
zoom = olZoom + this.minZoomLevel;
|
||
|
if (this.map.baseLayer !== this) {
|
||
|
zoom = this.getZoomForResolution(
|
||
|
this.map.baseLayer.getResolutionForZoom(zoom)
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
return zoom;
|
||
|
},
|
||
|
|
||
|
CLASS_NAME: "SuperMap.Layer.FixedZoomLevels"
|
||
|
});
|
||
|
|