|
/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for |
|
* full list of contributors). 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/SphericalMercator.js |
|
* @requires OpenLayers/Layer/EventPane.js |
|
* @requires OpenLayers/Layer/FixedZoomLevels.js |
|
*/ |
|
|
|
/** |
|
* Class: OpenLayers.Layer.Google |
|
* |
|
* Inherits from: |
|
* - <OpenLayers.Layer.SphericalMercator> |
|
* - <OpenLayers.Layer.EventPane> |
|
* - <OpenLayers.Layer.FixedZoomLevels> |
|
*/ |
|
OpenLayers.Layer.Google = OpenLayers.Class( |
|
OpenLayers.Layer.EventPane, |
|
OpenLayers.Layer.FixedZoomLevels, { |
|
|
|
/** |
|
* Constant: MIN_ZOOM_LEVEL |
|
* {Integer} 0 |
|
*/ |
|
MIN_ZOOM_LEVEL: 0, |
|
|
|
/** |
|
* Constant: MAX_ZOOM_LEVEL |
|
* {Integer} 21 |
|
*/ |
|
MAX_ZOOM_LEVEL: 21, |
|
|
|
/** |
|
* Constant: RESOLUTIONS |
|
* {Array(Float)} Hardcode these resolutions so that they are more closely |
|
* tied with the standard wms projection |
|
*/ |
|
RESOLUTIONS: [ |
|
1.40625, |
|
0.703125, |
|
0.3515625, |
|
0.17578125, |
|
0.087890625, |
|
0.0439453125, |
|
0.02197265625, |
|
0.010986328125, |
|
0.0054931640625, |
|
0.00274658203125, |
|
0.001373291015625, |
|
0.0006866455078125, |
|
0.00034332275390625, |
|
0.000171661376953125, |
|
0.0000858306884765625, |
|
0.00004291534423828125, |
|
0.00002145767211914062, |
|
0.00001072883605957031, |
|
0.00000536441802978515, |
|
0.00000268220901489257, |
|
0.0000013411045074462891, |
|
0.00000067055225372314453 |
|
], |
|
|
|
/** |
|
* APIProperty: type |
|
* {GMapType} |
|
*/ |
|
type: null, |
|
|
|
/** |
|
* APIProperty: wrapDateLine |
|
* {Boolean} Allow user to pan forever east/west. Default is true. |
|
* Setting this to false only restricts panning if |
|
* <sphericalMercator> is true. |
|
*/ |
|
wrapDateLine: true, |
|
|
|
/** |
|
* APIProperty: sphericalMercator |
|
* {Boolean} Should the map act as a mercator-projected map? This will |
|
* cause all interactions with the map to be in the actual map |
|
* projection, which allows support for vector drawing, overlaying |
|
* other maps, etc. |
|
*/ |
|
sphericalMercator: false, |
|
|
|
/** |
|
* Property: version |
|
* {Number} The version of the Google Maps API |
|
*/ |
|
version: null, |
|
|
|
/** |
|
* Constructor: OpenLayers.Layer.Google |
|
* |
|
* Parameters: |
|
* name - {String} A name for the layer. |
|
* options - {Object} An optional object whose properties will be set |
|
* on the layer. |
|
*/ |
|
initialize: function(name, options) { |
|
options = options || {}; |
|
if(!options.version) { |
|
options.version = typeof GMap2 === "function" ? "2" : "3"; |
|
} |
|
var mixin = OpenLayers.Layer.Google["v" + |
|
options.version.replace(/\./g, "_")]; |
|
if (mixin) { |
|
OpenLayers.Util.applyDefaults(options, mixin); |
|
} else { |
|
throw "Unsupported Google Maps API version: " + options.version; |
|
} |
|
|
|
OpenLayers.Util.applyDefaults(options, mixin.DEFAULTS); |
|
if (options.maxExtent) { |
|
options.maxExtent = options.maxExtent.clone(); |
|
} |
|
|
|
OpenLayers.Layer.EventPane.prototype.initialize.apply(this, |
|
[name, options]); |
|
OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this, |
|
[name, options]); |
|
|
|
if (this.sphericalMercator) { |
|
OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator); |
|
this.initMercatorParameters(); |
|
} |
|
}, |
|
|
|
/** |
|
* Method: clone |
|
* Create a clone of this layer |
|
* |
|
* Returns: |
|
* {<OpenLayers.Layer.Google>} An exact clone of this layer |
|
*/ |
|
clone: function() { |
|
/** |
|
* This method isn't intended to be called by a subclass and it |
|
* doesn't call the same method on the superclass. We don't call |
|
* the super's clone because we don't want properties that are set |
|
* on this layer after initialize (i.e. this.mapObject etc.). |
|
*/ |
|
return new OpenLayers.Layer.Google( |
|
this.name, this.getOptions() |
|
); |
|
}, |
|
|
|
/** |
|
* APIMethod: setVisibility |
|
* Set the visibility flag for the layer and hide/show & redraw |
|
* accordingly. Fire event unless otherwise specified |
|
* |
|
* Note that visibility is no longer simply whether or not the layer's |
|
* style.display is set to "block". Now we store a 'visibility' state |
|
* property on the layer class, this allows us to remember whether or |
|
* not we *desire* for a layer to be visible. In the case where the |
|
* map's resolution is out of the layer's range, this desire may be |
|
* subverted. |
|
* |
|
* Parameters: |
|
* visible - {Boolean} Display the layer (if in range) |
|
*/ |
|
setVisibility: function(visible) { |
|
// sharing a map container, opacity has to be set per layer |
|
var opacity = this.opacity == null ? 1 : this.opacity; |
|
OpenLayers.Layer.EventPane.prototype.setVisibility.apply(this, arguments); |
|
this.setOpacity(opacity); |
|
}, |
|
|
|
/** |
|
* APIMethod: display |
|
* Hide or show the Layer |
|
* |
|
* Parameters: |
|
* display - {Boolean} |
|
*/ |
|
display: function(visible) { |
|
if (!this._dragging) { |
|
this.setGMapVisibility(visible); |
|
} |
|
OpenLayers.Layer.EventPane.prototype.display.apply(this, arguments); |
|
}, |
|
|
|
/** |
|
* Method: moveTo |
|
* |
|
* Parameters: |
|
* bound - {<OpenLayers.Bounds>} |
|
* zoomChanged - {Boolean} Tells when zoom has changed, as layers have to |
|
* do some init work in that case. |
|
* dragging - {Boolean} |
|
*/ |
|
moveTo: function(bounds, zoomChanged, dragging) { |
|
this._dragging = dragging; |
|
OpenLayers.Layer.EventPane.prototype.moveTo.apply(this, arguments); |
|
delete this._dragging; |
|
}, |
|
|
|
/** |
|
* APIMethod: setOpacity |
|
* Sets the opacity for the entire layer (all images) |
|
* |
|
* Parameter: |
|
* opacity - {Float} |
|
*/ |
|
setOpacity: function(opacity) { |
|
if (opacity !== this.opacity) { |
|
if (this.map != null) { |
|
this.map.events.triggerEvent("changelayer", { |
|
layer: this, |
|
property: "opacity" |
|
}); |
|
} |
|
this.opacity = opacity; |
|
} |
|
// Though this layer's opacity may not change, we're sharing a container |
|
// and need to update the opacity for the entire container. |
|
if (this.getVisibility()) { |
|
var container = this.getMapContainer(); |
|
OpenLayers.Util.modifyDOMElement( |
|
container, null, null, null, null, null, null, opacity |
|
); |
|
} |
|
}, |
|
|
|
/** |
|
* APIMethod: destroy |
|
* Clean up this layer. |
|
*/ |
|
destroy: function() { |
|
/** |
|
* We have to override this method because the event pane destroy |
|
* deletes the mapObject reference before removing this layer from |
|
* the map. |
|
*/ |
|
if (this.map) { |
|
this.setGMapVisibility(false); |
|
var cache = OpenLayers.Layer.Google.cache[this.map.id]; |
|
if (cache && cache.count <= 1) { |
|
this.removeGMapElements(); |
|
} |
|
} |
|
OpenLayers.Layer.EventPane.prototype.destroy.apply(this, arguments); |
|
}, |
|
|
|
/** |
|
* Method: removeGMapElements |
|
* Remove all elements added to the dom. This should only be called if |
|
* this is the last of the Google layers for the given map. |
|
*/ |
|
removeGMapElements: function() { |
|
var cache = OpenLayers.Layer.Google.cache[this.map.id]; |
|
if (cache) { |
|
// remove shared elements from dom |
|
var container = this.mapObject && this.getMapContainer(); |
|
if (container && container.parentNode) { |
|
container.parentNode.removeChild(container); |
|
} |
|
var termsOfUse = cache.termsOfUse; |
|
if (termsOfUse && termsOfUse.parentNode) { |
|
termsOfUse.parentNode.removeChild(termsOfUse); |
|
} |
|
var poweredBy = cache.poweredBy; |
|
if (poweredBy && poweredBy.parentNode) { |
|
poweredBy.parentNode.removeChild(poweredBy); |
|
} |
|
} |
|
}, |
|
|
|
/** |
|
* APIMethod: removeMap |
|
* On being removed from the map, also remove termsOfUse and poweredBy divs |
|
* |
|
* Parameters: |
|
* map - {<OpenLayers.Map>} |
|
*/ |
|
removeMap: function(map) { |
|
// hide layer before removing |
|
if (this.visibility && this.mapObject) { |
|
this.setGMapVisibility(false); |
|
} |
|
// check to see if last Google layer in this map |
|
var cache = OpenLayers.Layer.Google.cache[map.id]; |
|
if (cache) { |
|
if (cache.count <= 1) { |
|
this.removeGMapElements(); |
|
delete OpenLayers.Layer.Google.cache[map.id]; |
|
} else { |
|
// decrement the layer count |
|
--cache.count; |
|
} |
|
} |
|
// remove references to gmap elements |
|
delete this.termsOfUse; |
|
delete this.poweredBy; |
|
delete this.mapObject; |
|
delete this.dragObject; |
|
OpenLayers.Layer.EventPane.prototype.removeMap.apply(this, arguments); |
|
}, |
|
|
|
// |
|
// TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds |
|
// |
|
|
|
/** |
|
* APIMethod: getOLBoundsFromMapObjectBounds |
|
* |
|
* Parameters: |
|
* moBounds - {Object} |
|
* |
|
* Returns: |
|
* {<OpenLayers.Bounds>} An <OpenLayers.Bounds>, translated from the |
|
* passed-in MapObject Bounds. |
|
* Returns null if null value is passed in. |
|
*/ |
|
getOLBoundsFromMapObjectBounds: function(moBounds) { |
|
var olBounds = null; |
|
if (moBounds != null) { |
|
var sw = moBounds.getSouthWest(); |
|
var ne = moBounds.getNorthEast(); |
|
if (this.sphericalMercator) { |
|
sw = this.forwardMercator(sw.lng(), sw.lat()); |
|
ne = this.forwardMercator(ne.lng(), ne.lat()); |
|
} else { |
|
sw = new OpenLayers.LonLat(sw.lng(), sw.lat()); |
|
ne = new OpenLayers.LonLat(ne.lng(), ne.lat()); |
|
} |
|
olBounds = new OpenLayers.Bounds(sw.lon, |
|
sw.lat, |
|
ne.lon, |
|
ne.lat ); |
|
} |
|
return olBounds; |
|
}, |
|
|
|
/** |
|
* APIMethod: getWarningHTML |
|
* |
|
* Returns: |
|
* {String} String with information on why layer is broken, how to get |
|
* it working. |
|
*/ |
|
getWarningHTML:function() { |
|
return OpenLayers.i18n("googleWarning"); |
|
}, |
|
|
|
|
|
/************************************ |
|
* * |
|
* MapObject Interface Controls * |
|
* * |
|
************************************/ |
|
|
|
|
|
// Get&Set Center, Zoom |
|
|
|
/** |
|
* APIMethod: getMapObjectCenter |
|
* |
|
* Returns: |
|
* {Object} The mapObject's current center in Map Object format |
|
*/ |
|
getMapObjectCenter: function() { |
|
return this.mapObject.getCenter(); |
|
}, |
|
|
|
/** |
|
* APIMethod: getMapObjectZoom |
|
* |
|
* Returns: |
|
* {Integer} The mapObject's current zoom, in Map Object format |
|
*/ |
|
getMapObjectZoom: function() { |
|
return this.mapObject.getZoom(); |
|
}, |
|
|
|
|
|