mirror of
				https://github.com/jiawanlong/Cesium-Examples.git
				synced 2025-11-04 09:14:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			322 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			322 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
 | 
						|
/**
 | 
						|
 * @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"
 | 
						|
});
 | 
						|
 |