Files
openlayers/lib/OpenLayers/Layer/Google/v3.js
ahocevar 978cb4be9f Only create Google control once
The control div is now an empty container that we can always append to and
remove from without having to worry about GMaps changing styles on it. It
also makes sure that the control is appended before Google's own
attribution control, so the "Report a map error" link will always be
clickable.
2012-12-06 11:44:49 +01:00

347 lines
11 KiB
JavaScript

/* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
* full list of contributors). Published under the 2-clause BSD license.
* See license.txt in the OpenLayers distribution or repository 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.
*
* To use this layer, you must include the GMaps v3 API in your html.
*
* 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)
* {
* 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
// create GMap
var center = this.map.getCenter();
var container = document.createElement('div');
container.className = "olForeignContainer";
container.style.width = '100%';
container.style.height = '100%';
mapObject = new google.maps.Map(container, {
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
});
var googleControl = document.createElement('div');
googleControl.style.width = '100%';
googleControl.style.height = '100%';
mapObject.controls[google.maps.ControlPosition.TOP_LEFT].push(googleControl);
// cache elements for use by any other google layers added to
// this same map
cache = {
googleControl: googleControl,
mapObject: mapObject,
count: 1
};
OpenLayers.Layer.Google.cache[this.map.id] = cache;
}
this.mapObject = mapObject;
this.setGMapVisibility(this.visibility);
},
/**
* APIMethod: onMapResize
*/
onMapResize: function() {
if (this.visibility) {
google.maps.event.trigger(this.mapObject, "resize");
}
},
/**
* 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) {
if (!cache.googleControl.hasChildNodes()) {
cache.googleControl.appendChild(this.map.viewPortDiv);
this.map.div.appendChild(container);
google.maps.event.trigger(this.mapObject, 'resize');
}
this.mapObject.setMapTypeId(type);
cache.displayed = this.id;
} else {
if (cache.googleControl.hasChildNodes()) {
this.map.div.removeChild(container);
this.map.div.appendChild(this.map.viewPortDiv);
}
delete cache.displayed;
}
}
},
/**
* 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);
}
};