This allows us to simplify the map and layer configuration, because now the projection also defines defaults for maxExtent, maxResolution and units. This change also adds transforms for SRS aliases for EPSG:4326 and centralizes axis order information in OpenLayers.Projection.defaults.
437 lines
14 KiB
JavaScript
437 lines
14 KiB
JavaScript
/* Copyright (c) 2006-2012 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 <= v3.6.
|
|
* 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. To use this layer,
|
|
* you must include the GMaps API (<= v3.6) in your html:
|
|
*
|
|
* (code)
|
|
* <script src="http://maps.google.com/maps/api/js?v=3.6&sensor=false"></script>
|
|
* (end)
|
|
*/
|
|
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)
|
|
* {
|
|
* sphericalMercator: true,
|
|
* projection: "EPSG:900913"
|
|
* }
|
|
* (end)
|
|
*/
|
|
DEFAULTS: {
|
|
sphericalMercator: true,
|
|
projection: "EPSG:900913"
|
|
},
|
|
|
|
/**
|
|
* APIProperty: animationEnabled
|
|
* {Boolean} If set to true, the transition between zoom levels will be
|
|
* animated (if supported by the GMaps API for the device used). Set to
|
|
* false to match the zooming experience of other layer types. Default
|
|
* is true. Note that the GMaps API does not give us control over zoom
|
|
* animation, so if set to false, when zooming, this will make the
|
|
* layer temporarily invisible, wait until GMaps reports the map being
|
|
* idle, and make it visible again. The result will be a blank layer
|
|
* for a few moments while zooming.
|
|
*/
|
|
animationEnabled: true,
|
|
|
|
/**
|
|
* 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,
|
|
streetViewControl: 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 Map Data popup to the container, if any
|
|
while (div.lastChild.style.display == "none") {
|
|
container.appendChild(div.lastChild);
|
|
}
|
|
|
|
// 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 {
|
|
var cache = OpenLayers.Layer.Google.cache[this.map.id];
|
|
if (!cache.resized) {
|
|
var layer = this;
|
|
google.maps.event.addListenerOnce(this.mapObject, "tilesloaded", function() {
|
|
google.maps.event.trigger(layer.mapObject, "resize");
|
|
layer.moveTo(layer.map.getCenter(), layer.map.getZoom());
|
|
delete cache.resized;
|
|
});
|
|
}
|
|
cache.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();
|
|
return this.getMapObjectPixelFromXY((1/res * (lon - extent.left)),
|
|
(1/res * (extent.top - lat)));
|
|
},
|
|
|
|
|
|
/**
|
|
* 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) {
|
|
if (this.animationEnabled === false && zoom != this.mapObject.zoom) {
|
|
var mapContainer = this.getMapContainer();
|
|
google.maps.event.addListenerOnce(
|
|
this.mapObject,
|
|
"idle",
|
|
function() {
|
|
mapContainer.style.visibility = "";
|
|
}
|
|
);
|
|
mapContainer.style.visibility = "hidden";
|
|
}
|
|
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}
|
|
*
|
|
* Returns:
|
|
* {Object} MapObject LonLat built from lon and lat params
|
|
*/
|
|
getMapObjectLonLatFromLonLat: function(lon, lat) {
|
|
var gLatLng;
|
|
if(this.sphericalMercator) {
|
|
var lonlat = this.inverseMercator(lon, lat);
|
|
gLatLng = new google.maps.LatLng(lonlat.lat, lonlat.lon);
|
|
} else {
|
|
gLatLng = new google.maps.LatLng(lat, lon);
|
|
}
|
|
return gLatLng;
|
|
},
|
|
|
|
// Pixel
|
|
|
|
/**
|
|
* APIMethod: getMapObjectPixelFromXY
|
|
*
|
|
* Parameters:
|
|
* x - {Integer}
|
|
* y - {Integer}
|
|
*
|
|
* Returns:
|
|
* {Object} MapObject Pixel from x and y parameters
|
|
*/
|
|
getMapObjectPixelFromXY: function(x, y) {
|
|
return new google.maps.Point(x, y);
|
|
},
|
|
|
|
/**
|
|
* APIMethod: destroy
|
|
* Clean up this layer.
|
|
*/
|
|
destroy: function() {
|
|
if (this.repositionListener) {
|
|
google.maps.event.removeListener(this.repositionListener);
|
|
}
|
|
if (this.repositionTimer) {
|
|
window.clearTimeout(this.repositionTimer);
|
|
}
|
|
OpenLayers.Layer.Google.prototype.destroy.apply(this, arguments);
|
|
}
|
|
|
|
};
|