1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 | /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD * license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the * full text of the license. */ /** * @requires OpenLayers/Layer.js */ /** * Class: OpenLayers.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 OpenLayers.Layer.getExent(), passing in * the desired resolution. With this extent, we then call getZoomForExtent() * * * Whenever you implement a layer using OpenLayers.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. * */ OpenLayers.Layer.FixedZoomLevels = OpenLayers.Class({ /********************************************************/ /* */ /* Baselayer Functions */ /* */ /* The following functions must all be implemented */ /* by all base layers */ /* */ /********************************************************/ /** * Constructor: OpenLayers.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 OpenLayers.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: * {<OpenLayers.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 OpenLayers.Pixel(0,0); var tlLL = this.getLonLatFromViewPortPx(tlPx); var brPx = new OpenLayers.Pixel(size.w, size.h); var brLL = this.getLonLatFromViewPortPx(brPx); if ((tlLL != null) && (brLL != null)) { extent = new OpenLayers.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 OpenLayers.Layer.prototype.getZoomForResolution.apply(this, arguments); } else { var extent = OpenLayers.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 <-> OpenLayers Zoom // /** * Method: getOLZoomFromMapObjectZoom * Get the OL zoom index from the map object zoom level * * Parameters: * moZoom - {Integer} * * Returns: * {Integer} An OpenLayers 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; } 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; } return zoom; }, CLASS_NAME: "OpenLayers.Layer.FixedZoomLevels" }); |