|
/* 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/Google.js |
|
*/ |
|
|
|
/** |
|
* Constant: OpenLayers.Layer.Google.v3 |
|
* |
|
* Mixin providing functionality specific to the Google Maps API v3. Note that |
|
* this layer configures the google.maps.map object with the "disableDefaultUI" |
|
* option set to true. Using UI controls that the Google Maps API provides is |
|
* not supported by the OpenLayers API. |
|
*/ |
|
OpenLayers.Layer.Google.v3 = { |
|
|
|
/** |
|
* Constant: DEFAULTS |
|
* {Object} It is not recommended to change the properties set here. Note |
|
* that Google.v3 layers only work when sphericalMercator is set to true. |
|
* |
|
* (code) |
|
* { |
|
* maxExtent: new OpenLayers.Bounds( |
|
* -128 * 156543.0339, |
|
* -128 * 156543.0339, |
|
* 128 * 156543.0339, |
|
* 128 * 156543.0339 |
|
* ), |
|
* sphericalMercator: true, |
|
* maxResolution: 156543.0339, |
|
* units: "m", |
|
* projection: "EPSG:900913" |
|
* } |
|
* (end) |
|
*/ |
|
DEFAULTS: { |
|
maxExtent: new OpenLayers.Bounds( |
|
-128 * 156543.0339, |
|
-128 * 156543.0339, |
|
128 * 156543.0339, |
|
128 * 156543.0339 |
|
), |
|
sphericalMercator: true, |
|
maxResolution: 156543.0339, |
|
units: "m", |
|
projection: "EPSG:900913" |
|
}, |
|
|
|
/** |
|
* Method: loadMapObject |
|
* Load the GMap and register appropriate event listeners. If we can't |
|
* load GMap2, then display a warning message. |
|
*/ |
|
loadMapObject:function() { |
|
if (!this.type) { |
|
this.type = google.maps.MapTypeId.ROADMAP; |
|
} |
|
var mapObject; |
|
var cache = OpenLayers.Layer.Google.cache[this.map.id]; |
|
if (cache) { |
|
// there are already Google layers added to this map |
|
mapObject = cache.mapObject; |
|
// increment the layer count |
|
++cache.count; |
|
} else { |
|
// this is the first Google layer for this map |
|
|
|
var container = this.map.viewPortDiv; |
|
var div = document.createElement("div"); |
|
div.id = this.map.id + "_GMapContainer"; |
|
div.style.position = "absolute"; |
|
div.style.width = "100%"; |
|
div.style.height = "100%"; |
|
container.appendChild(div); |
|
|
|
// create GMap and shuffle elements |
|
var center = this.map.getCenter(); |
|
mapObject = new google.maps.Map(div, { |
|
center: center ? |
|
new google.maps.LatLng(center.lat, center.lon) : |
|
new google.maps.LatLng(0, 0), |
|
zoom: this.map.getZoom() || 0, |
|
mapTypeId: this.type, |
|
disableDefaultUI: true, |
|
keyboardShortcuts: false, |
|
draggable: false, |
|
disableDoubleClickZoom: true, |
|
scrollwheel: false |
|
}); |
|
|
|
// cache elements for use by any other google layers added to |
|
// this same map |
|
cache = { |
|
mapObject: mapObject, |
|
count: 1 |
|
}; |
|
OpenLayers.Layer.Google.cache[this.map.id] = cache; |
|
this.repositionListener = google.maps.event.addListenerOnce( |
|
mapObject, |
|
"center_changed", |
|
OpenLayers.Function.bind(this.repositionMapElements, this) |
|
); |
|
} |
|
this.mapObject = mapObject; |
|
this.setGMapVisibility(this.visibility); |
|
}, |
|
|
|
/** |
|
* Method: repositionMapElements |
|
* |
|
* Waits until powered by and terms of use elements are available and then |
|
* moves them so they are clickable. |
|
*/ |
|
repositionMapElements: function() { |
|
|
|
// This is the first time any Google layer in this mapObject has been |
|
// made visible. The mapObject needs to know the container size. |
|
google.maps.event.trigger(this.mapObject, "resize"); |
|
|
|
var div = this.mapObject.getDiv().firstChild; |
|
if (!div || div.childNodes.length < 3) { |
|
this.repositionTimer = window.setTimeout( |
|
OpenLayers.Function.bind(this.repositionMapElements, this), |
|
250 |
|
); |
|
return false; |
|
} |
|
|
|
var cache = OpenLayers.Layer.Google.cache[this.map.id]; |
|
var container = this.map.viewPortDiv; |
|
|
|
// move the ToS and branding stuff up to the container div |
|
var termsOfUse = div.lastChild; |
|
container.appendChild(termsOfUse); |
|
termsOfUse.style.zIndex = "1100"; |
|
termsOfUse.style.bottom = ""; |
|
termsOfUse.className = "olLayerGoogleCopyright olLayerGoogleV3"; |
|
termsOfUse.style.display = ""; |
|
cache.termsOfUse = termsOfUse; |
|
|
|
var poweredBy = div.lastChild; |
|
container.appendChild(poweredBy); |
|
poweredBy.style.zIndex = "1100"; |
|
poweredBy.style.bottom = ""; |
|
poweredBy.className = "olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint"; |
|
poweredBy.style.display = ""; |
|
cache.poweredBy = poweredBy; |
|
|
|
this.setGMapVisibility(this.visibility); |
|
|
|
}, |
|
|
|
/** |
|
* APIMethod: onMapResize |
|
*/ |
|
onMapResize: function() { |
|
if (this.visibility) { |
|
google.maps.event.trigger(this.mapObject, "resize"); |
|
} else { |
|
if (!this._resized) { |
|
var layer = this; |
|
google.maps.event.addListenerOnce(this.mapObject, "tilesloaded", function() { |
|
delete layer._resized; |
|
google.maps.event.trigger(layer.mapObject, "resize"); |
|
layer.moveTo(layer.map.getCenter(), layer.map.getZoom()); |
|
}); |
|
} |
|
this._resized = true; |
|
} |
|
}, |
|
|
|
/** |
|
* Method: setGMapVisibility |
|
* Display the GMap container and associated elements. |
|
* |
|
* Parameters: |
|
* visible - {Boolean} Display the GMap elements. |
|
*/ |
|
setGMapVisibility: function(visible) { |
|
var cache = OpenLayers.Layer.Google.cache[this.map.id]; |
|
if (cache) { |
|
var type = this.type; |
|
var layers = this.map.layers; |
|
var layer; |
|
for (var i=layers.length-1; i>=0; --i) { |
|
layer = layers[i]; |
|
if (layer instanceof OpenLayers.Layer.Google && |
|
layer.visibility === true && layer.inRange === true) { |
|
type = layer.type; |
|
visible = true; |
|
break; |
|
} |
|
} |
|
var container = this.mapObject.getDiv(); |
|
if (visible === true) { |
|
this.mapObject.setMapTypeId(type); |
|
container.style.left = ""; |
|
if (cache.termsOfUse && cache.termsOfUse.style) { |
|
cache.termsOfUse.style.left = ""; |
|
cache.termsOfUse.style.display = ""; |
|
cache.poweredBy.style.display = ""; |
|
} |
|
cache.displayed = this.id; |
|
} else { |
|
delete cache.displayed; |
|
container.style.left = "-9999px"; |
|
if (cache.termsOfUse && cache.termsOfUse.style) { |
|
cache.termsOfUse.style.display = "none"; |
|
// move ToU far to the left in addition to setting |
|
// display to "none", because at the end of the GMap |
|
// load sequence, display: none will be unset and ToU |
|
// would be visible after loading a map with a google |
|
// layer that is initially hidden. |
|
cache.termsOfUse.style.left = "-9999px"; |
|
cache.poweredBy.style.display = "none"; |
|
} |
|
} |
|
} |
|
}, |
|
|
|
/** |
|
* Method: getMapContainer |
|
* |
|
* Returns: |
|
* {DOMElement} the GMap container's div |
|
*/ |
|
getMapContainer: function() { |
|
return this.mapObject.getDiv(); |
|
}, |
|
|
|
// |
|
// TRANSLATION: MapObject Bounds <-> OpenLayers.Bounds |
|
// |
|
|
|
/** |
|
* APIMethod: getMapObjectBoundsFromOLBounds |
|
* |
|
* Parameters: |
|
* olBounds - {<OpenLayers.Bounds>} |
|
* |
|
* Returns: |
|
* {Object} A MapObject Bounds, translated from olBounds |
|
* Returns null if null value is passed in |
|
*/ |
|
getMapObjectBoundsFromOLBounds: function(olBounds) { |
|
var moBounds = null; |
|
if (olBounds != null) { |
|
var sw = this.sphericalMercator ? |
|
this.inverseMercator(olBounds.bottom, olBounds.left) : |
|
new OpenLayers.LonLat(olBounds.bottom, olBounds.left); |
|
var ne = this.sphericalMercator ? |
|
this.inverseMercator(olBounds.top, olBounds.right) : |
|
new OpenLayers.LonLat(olBounds.top, olBounds.right); |
|
moBounds = new google.maps.LatLngBounds( |
|
new google.maps.LatLng(sw.lat, sw.lon), |
|
new google.maps.LatLng(ne.lat, ne.lon) |
|
); |
|
} |
|
return moBounds; |
|
}, |
|
|
|
|
|
/************************************ |
|
* * |
|
* MapObject Interface Controls * |
|
* * |
|
************************************/ |
|
|
|
|
|
// LonLat - Pixel Translation |
|
|
|
/** |
|
* APIMethod: getMapObjectLonLatFromMapObjectPixel |
|
* |
|
* Parameters: |
|
* moPixel - {Object} MapObject Pixel format |
|
* |
|
* Returns: |
|
* {Object} MapObject LonLat translated from MapObject Pixel |
|
*/ |
|
getMapObjectLonLatFromMapObjectPixel: function(moPixel) { |
|
var size = this.map.getSize(); |
|
var lon = this.getLongitudeFromMapObjectLonLat(this.mapObject.center); |
|
var lat = this.getLatitudeFromMapObjectLonLat(this.mapObject.center); |
|
var res = this.map.getResolution(); |
|
|
|
var delta_x = moPixel.x - (size.w / 2); |
|
var delta_y = moPixel.y - (size.h / 2); |
|
|
|
var lonlat = new OpenLayers.LonLat( |
|
lon + delta_x * res, |
|
lat - delta_y * res |
|
); |
|
|
|
if (this.wrapDateLine) { |
|
lonlat = lonlat.wrapDateLine(this.maxExtent); |
|
} |
|
return this.getMapObjectLonLatFromLonLat(lonlat.lon, lonlat.lat); |
|
}, |
|
|
|
/** |
|
* APIMethod: getMapObjectPixelFromMapObjectLonLat |
|
* |
|
* Parameters: |
|
* moLonLat - {Object} MapObject LonLat format |
|
* |
|
* Returns: |
|
* {Object} MapObject Pixel transtlated from MapObject LonLat |
|
*/ |
|
getMapObjectPixelFromMapObjectLonLat: function(moLonLat) { |
|
var lon = this.getLongitudeFromMapObjectLonLat(moLonLat); |
|
var lat = this.getLatitudeFromMapObjectLonLat(moLonLat); |
|
var res = this.map.getResolution(); |
|
var extent = this.map.getExtent(); |
|
var px = new OpenLayers.Pixel( |
|
(1/res * (lon - extent.left)), |
|
(1/res * (extent.top - lat)) |
|
); |
|
return this.getMapObjectPixelFromXY(px.x, px.y); |
|
}, |
|
|
|
|
|
/** |
|
* APIMethod: setMapObjectCenter |
|
* Set the mapObject to the specified center and zoom |
|
* |
|
* Parameters: |
|
* center - {Object} MapObject LonLat format |
|
* zoom - {int} MapObject zoom format |
|
*/ |
|
setMapObjectCenter: function(center, zoom) { |
|
this.mapObject.setOptions({ |
|
center: center, |
|
zoom: zoom |
|
}); |
|
}, |
|
|
|
|
|
// Bounds |
|
|
|
/** |
|
* APIMethod: getMapObjectZoomFromMapObjectBounds |
|
* |
|
* Parameters: |
|
* moBounds - {Object} MapObject Bounds format |
|
* |
|
* Returns: |
|
* {Object} MapObject Zoom for specified MapObject Bounds |
|
*/ |
|
getMapObjectZoomFromMapObjectBounds: function(moBounds) { |
|
return this.mapObject.getBoundsZoomLevel(moBounds); |
|
}, |
|
|
|
/************************************ |
|
* * |
|
* MapObject Primitives * |
|
* * |
|
************************************/ |
|
|
|
|
|
// LonLat |
|
|
|
/** |
|
* APIMethod: getMapObjectLonLatFromLonLat |
|
* |
|
* Parameters: |
|
* lon - {Float} |
|
* lat - {Float} |