Files
openlayers/lib/OpenLayers/Layer/Google.js
crschmidt 66a19c70ef Fix for GMaps layers to display in correct position when they were originally
loaded as the not default layer, or the map is resized while the gmaps layer is
hidden. Patch put together by Edgemaster (thanks), (Closes #830)  


git-svn-id: http://svn.openlayers.org/trunk/openlayers@7300 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
2008-05-31 17:19:48 +00:00

546 lines
15 KiB
JavaScript

/* Copyright (c) 2006-2008 MetaCarta, Inc., 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} 19
*/
MAX_ZOOM_LEVEL: 19,
/**
* 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
],
/**
* APIProperty: type
* {GMapType}
*/
type: null,
/**
* 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: dragObject
* {GDraggableObject} Since 2.93, Google has exposed the ability to get
* the maps GDraggableObject. We can now use this for smooth panning
*/
dragObject: 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) {
OpenLayers.Layer.EventPane.prototype.initialize.apply(this, arguments);
OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,
arguments);
this.addContainerPxFunction();
if (this.sphericalMercator) {
OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator);
this.initMercatorParameters();
}
},
/**
* Method: loadMapObject
* Load the GMap and register appropriate event listeners. If we can't
* load GMap2, then display a warning message.
*/
loadMapObject:function() {
//has gmaps library has been loaded?
try {
// create GMap, hide nav controls
this.mapObject = new GMap2( this.div );
//since v 2.93 getDragObject is now available.
if(typeof this.mapObject.getDragObject == "function") {
this.dragObject = this.mapObject.getDragObject();
} else {
this.dragPanMapObject = null;
}
// move the ToS and branding stuff up to the pane
// thanks a *mil* Erik for thinking of this
var poweredBy = this.div.lastChild;
this.div.removeChild(poweredBy);
this.pane.appendChild(poweredBy);
poweredBy.className = "olLayerGooglePoweredBy gmnoprint";
poweredBy.style.left = "";
poweredBy.style.bottom = "";
var termsOfUse = this.div.lastChild;
this.div.removeChild(termsOfUse);
this.pane.appendChild(termsOfUse);
termsOfUse.className = "olLayerGoogleCopyright";
termsOfUse.style.right = "";
termsOfUse.style.bottom = "";
} catch (e) {
OpenLayers.Console.error(e);
}
},
/**
* APIMethod: setMap
* Overridden from EventPane because if a map type has been specified,
* we need to attach a listener for the first moveend -- this is how
* we will know that the map has been centered. Only once the map has
* been centered is it safe to change the gmap object's map type.
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
setMap: function(map) {
OpenLayers.Layer.EventPane.prototype.setMap.apply(this, arguments);
if (this.type != null) {
this.map.events.register("moveend", this, this.setMapType);
}
},
/**
* Method: setMapType
* The map has been centered, and a map type was specified, so we
* set the map type on the gmap object, then unregister the listener
* so that we dont keep doing this every time the map moves.
*/
setMapType: function() {
if (this.mapObject.getCenter() != null) {
// Support for custom map types.
if (OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),
this.type) == -1) {
this.mapObject.addMapType(this.type);
}
this.mapObject.setMapType(this.type);
this.map.events.unregister("moveend", this, this.setMapType);
}
},
/**
* APIMethod: onMapResize
*
* Parameters:
* evt - {Event}
*/
onMapResize: function() {
if(this.visibility) {
this.mapObject.checkResize();
} else {
this.windowResized = true;
}
},
/**
* Method: display
* Hide or show the layer
*
* Parameters:
* display - {Boolean}
*/
display: function(display) {
OpenLayers.Layer.EventPane.prototype.display.apply(this, arguments);
if(this.div.style.display == "block" && this.windowResized) {
this.mapObject.checkResize();
this.windowResized = false;
}
},
/**
* APIMethod: getZoomForExtent
*
* Parameters:
* bounds - {<OpenLayers.Bounds>}
*
* Returns:
* {Integer} Corresponding zoom level for a specified Bounds.
* If mapObject is not loaded or not centered, returns null
*
getZoomForExtent: function (bounds) {
var zoom = null;
if (this.mapObject != null) {
var moBounds = this.getMapObjectBoundsFromOLBounds(bounds);
var moZoom = this.getMapObjectZoomFromMapObjectBounds(moBounds);
//make sure zoom is within bounds
var moZoom = Math.min(Math.max(moZoom, this.minZoomLevel),
this.maxZoomLevel);
zoom = this.getOLZoomFromMapObjectZoom(moZoom);
}
return zoom;
},
*/
//
// 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: 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 GLatLngBounds(new GLatLng(sw.lat, sw.lon),
new GLatLng(ne.lat, ne.lon));
}
return moBounds;
},
/**
* Method: addContainerPxFunction
* Hack-on function because GMAPS does not give it to us
*
* Parameters:
* gLatLng - {GLatLng}
*
* Returns:
* {GPoint} A GPoint specifying gLatLng translated into "Container" coords
*/
addContainerPxFunction: function() {
if ( (typeof GMap2 != "undefined") &&
!GMap2.prototype.fromLatLngToContainerPixel) {
GMap2.prototype.fromLatLngToContainerPixel = function(gLatLng) {
// first we translate into "DivPixel"
var gPoint = this.fromLatLngToDivPixel(gLatLng);
// locate the sliding "Div" div
var div = this.getContainer().firstChild.firstChild;
// adjust by the offset of "Div" and voila!
gPoint.x += div.offsetLeft;
gPoint.y += div.offsetTop;
return gPoint;
};
}
},
/**
* 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: 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.setCenter(center, zoom);
},
/**
* APIMethod: dragPanMapObject
*
* Parameters:
* dX - {Integer}
* dY - {Integer}
*/
dragPanMapObject: function(dX, dY) {
this.dragObject.moveBy(new GSize(-dX, dY));
},
/**
* 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();
},
// LonLat - Pixel Translation
/**
* APIMethod: getMapObjectLonLatFromMapObjectPixel
*
* Parameters:
* moPixel - {Object} MapObject Pixel format
*
* Returns:
* {Object} MapObject LonLat translated from MapObject Pixel
*/
getMapObjectLonLatFromMapObjectPixel: function(moPixel) {
return this.mapObject.fromContainerPixelToLatLng(moPixel);
},
/**
* APIMethod: getMapObjectPixelFromMapObjectLonLat
*
* Parameters:
* moLonLat - {Object} MapObject LonLat format
*
* Returns:
* {Object} MapObject Pixel transtlated from MapObject LonLat
*/
getMapObjectPixelFromMapObjectLonLat: function(moLonLat) {
return this.mapObject.fromLatLngToContainerPixel(moLonLat);
},
// 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: getLongitudeFromMapObjectLonLat
*
* Parameters:
* moLonLat - {Object} MapObject LonLat format
*
* Returns:
* {Float} Longitude of the given MapObject LonLat
*/
getLongitudeFromMapObjectLonLat: function(moLonLat) {
return this.sphericalMercator ?
this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lon :
moLonLat.lng();
},
/**
* APIMethod: getLatitudeFromMapObjectLonLat
*
* Parameters:
* moLonLat - {Object} MapObject LonLat format
*
* Returns:
* {Float} Latitude of the given MapObject LonLat
*/
getLatitudeFromMapObjectLonLat: function(moLonLat) {
var lat = this.sphericalMercator ?
this.forwardMercator(moLonLat.lng(), moLonLat.lat()).lat :
moLonLat.lat();
return lat;
},
/**
* 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 GLatLng(lonlat.lat, lonlat.lon);
} else {
gLatLng = new GLatLng(lat, lon);
}
return gLatLng;
},
// Pixel
/**
* APIMethod: getXFromMapObjectPixel
*
* Parameters:
* moPixel - {Object} MapObject Pixel format
*
* Returns:
* {Integer} X value of the MapObject Pixel
*/
getXFromMapObjectPixel: function(moPixel) {
return moPixel.x;
},
/**
* APIMethod: getYFromMapObjectPixel
*
* Parameters:
* moPixel - {Object} MapObject Pixel format
*
* Returns:
* {Integer} Y value of the MapObject Pixel
*/
getYFromMapObjectPixel: function(moPixel) {
return moPixel.y;
},
/**
* APIMethod: getMapObjectPixelFromXY
*
* Parameters:
* x - {Integer}
* y - {Integer}
*
* Returns:
* {Object} MapObject Pixel from x and y parameters
*/
getMapObjectPixelFromXY: function(x, y) {
return new GPoint(x, y);
},
CLASS_NAME: "OpenLayers.Layer.Google"
});