+++ /dev/null
-/* Copyright (c) 2006 MetaCarta, Inc., published under the BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/license.txt for the full
- * text of the license. */
-// @require: OpenLayers/Util.js
-/**
-* @class
-*
-*
-*/
-
-OpenLayers.Map = Class.create();
-OpenLayers.Map.prototype = {
- // Hash: base z-indexes for different classes of thing
- Z_INDEX_BASE: { Layer: 100, Popup: 200, Control: 1000 },
-
- // Array: supported application event types
- EVENT_TYPES: [
- "addlayer", "removelayer", "movestart", "move", "moveend",
- "zoomend", "layerchanged", "popupopen", "popupclose",
- "addmarker", "removemarker", "clearmarkers", "mouseover",
- "mouseout", "mousemove", "dragstart", "drag", "dragend" ],
-
- // int: zoom levels, used to draw zoom dragging control and limit zooming
- maxZoomLevel: 16,
-
- // OpenLayers.Bounds
- maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90),
-
- /* projection */
- projection: "EPSG:4326",
-
- /** @type OpenLayers.Size */
- size: null,
-
- // float
- maxResolution: 1.40625, // degrees per pixel
- // Default is whole world in 256 pixels, from GMaps
-
- // DOMElement: the div that our map lives in
- div: null,
-
- // HTMLDivElement: the map's view port
- viewPortDiv: null,
-
- // HTMLDivElement: the map's layer container
- layerContainerDiv: null,
-
- // Array(OpenLayers.Layer): ordered list of layers in the map
- layers: null,
-
- // Array(OpenLayers.Control)
- controls: null,
-
- // Array(OpenLayers.Popup)
- popups: null,
-
- // OpenLayers.LonLat
- center: null,
-
- // int
- zoom: null,
-
- // OpenLayers.Events
- events: null,
-
- // OpenLayers.Pixel
- mouseDragStart: null,
-
- /** @type OpenLayers.Layer */
- baseLayer: null,
-
- /**
- * @param {DOMElement} div
- */
- initialize: function (div, options) {
- Object.extend(this, options);
-
- this.div = div = $(div);
-
- // the viewPortDiv is the outermost div we modify
- var id = div.id + "_OpenLayers_ViewPort";
- this.viewPortDiv = OpenLayers.Util.createDiv(id, null, null, null,
- "relative", null,
- "hidden");
- this.viewPortDiv.style.width = "100%";
- this.viewPortDiv.style.height = "100%";
- this.div.appendChild(this.viewPortDiv);
-
- // the layerContainerDiv is the one that holds all the layers
- id = div.id + "_OpenLayers_Container";
- this.layerContainerDiv = OpenLayers.Util.createDiv(id);
- this.viewPortDiv.appendChild(this.layerContainerDiv);
-
- this.events = new OpenLayers.Events(this, div, this.EVENT_TYPES);
-
- this.updateSize();
- // make the entire maxExtent fix in zoom level 0 by default
- if (this.maxResolution == null || this.maxResolution == "auto") {
- this.maxResolution = Math.max(
- this.maxExtent.getWidth() / this.size.w,
- this.maxExtent.getHeight() / this.size.h );
- }
- // update the internal size register whenever the div is resized
- this.events.register("resize", this, this.updateSize);
-
- this.layers = [];
-
- if (!this.controls) {
- this.controls = [];
- this.addControl(new OpenLayers.Control.MouseDefaults());
- this.addControl(new OpenLayers.Control.PanZoom());
- }
-
- this.popups = new Array();
-
- // always call map.destroy()
- Event.observe(window, 'unload',
- this.destroy.bindAsEventListener(this));
- },
-
- /**
- * @private
- */
- destroy:function() {
- if (this.layers != null) {
- for(var i=0; i< this.layers.length; i++) {
- this.layers[i].destroy();
- }
- this.layers = null;
- }
- if (this.controls != null) {
- for(var i=0; i< this.controls.length; i++) {
- this.controls[i].destroy();
- }
- this.controls = null;
- }
- },
-
- /**
- * @param {OpenLayers.Layer} layer
- */
- addLayer: function (layer) {
- layer.setMap(this);
- layer.div.style.overflow = "";
- layer.div.style.zIndex = this.Z_INDEX_BASE['Layer'] + this.layers.length;
-
- if (layer.viewPortLayer) {
- this.viewPortDiv.appendChild(layer.div);
- } else {
- this.layerContainerDiv.appendChild(layer.div);
- }
- this.layers.push(layer);
-
- // hack hack hack - until we add a more robust layer switcher,
- // which is able to determine which layers are base layers and
- // which are not (and put baselayers in a radiobutton group and
- // other layers in checkboxes) this seems to be the most straight-
- // forward way of dealing with this.
- //
- if (layer.isBaseLayer()) {
- this.baseLayer = layer;
- }
- this.events.triggerEvent("addlayer");
- },
-
- /** Removes a layer from the map by removing its visual element (the
- * layer.div property), then removing it from the map's internal list
- * of layers, setting the layer's map property to null.
- *
- * a "removelayer" event is triggered.
- *
- * very worthy of mention is that simply removing a layer from a map
- * will not cause the removal of any popups which may have been created
- * by the layer. this is due to the fact that it was decided at some
- * point that popups would not belong to layers. thus there is no way
- * for us to know here to which layer the popup belongs.
- *
- * A simple solution to this is simply to call destroy() on the layer.
- * the default OpenLayers.Layer class's destroy() function
- * automatically takes care to remove itself from whatever map it has
- * been attached to.
- *
- * The correct solution is for the layer itself to register an
- * event-handler on "removelayer" and when it is called, if it
- * recognizes itself as the layer being removed, then it cycles through
- * its own personal list of popups, removing them from the map.
- *
- * @param {OpenLayers.Layer} layer
- */
- removeLayer: function(layer) {
- this.layerContainerDiv.removeChild(layer.div);
- this.layers.remove(layer);
- layer.map = null;
- this.events.triggerEvent("removelayer");
- },
-
- /**
- * @param {Array(OpenLayers.Layer)} layers
- */
- addLayers: function (layers) {
- for (var i = 0; i < layers.length; i++) {
- this.addLayer(layers[i]);
- }
- },
-
- /**
- * @param {OpenLayers.Control} control
- * @param {OpenLayers.Pixel} px
- */
- addControl: function (control, px) {
- control.map = this;
- this.controls.push(control);
- var div = control.draw(px);
- if (div) {
- div.style.zIndex = this.Z_INDEX_BASE['Control'] +
- this.controls.length;
- this.viewPortDiv.appendChild( div );
- }
- },
-
- /**
- * @param {OpenLayers.Popup} popup
- */
- addPopup: function(popup) {
- popup.map = this;
- this.popups.push(popup);
- var popupDiv = popup.draw();
- if (popupDiv) {
- popupDiv.style.zIndex = this.Z_INDEX_BASE['Popup'] +
- this.popups.length;
- this.layerContainerDiv.appendChild(popupDiv);
- }
- },
-
- /**
- * @param {OpenLayers.Popup} popup
- */
- removePopup: function(popup) {
- this.popups.remove(popup);
- if (popup.div) {
- this.layerContainerDiv.removeChild(popup.div);
- }
- popup.map = null;
- },
-
- /**
- * @return {float}
- */
- getResolution: function () {
- // return degrees per pixel
- return this.maxResolution / Math.pow(2, this.zoom);
- },
-
- /**
- * @return {int}
- */
- getZoom: function () {
- return this.zoom;
- },
-
- /**
- * @returns {OpenLayers.Size}
- */
- getSize: function () {
- return this.size;
- },
-
- /**
- * @private
- */
- updateSize: function() {
- this.size = new OpenLayers.Size(
- this.div.clientWidth, this.div.clientHeight);
- this.events.div.offsets = null;
- // Workaround for the fact that hidden elements return 0 for size.
- if (this.size.w == 0 && this.size.h == 0) {
- var dim = Element.getDimensions(this.div);
- this.size.w = dim.width;
- this.size.h = dim.height;
- }
- if (this.size.w == 0 && this.size.h == 0) {
- this.size.w = parseInt(this.div.style.width);
- this.size.h = parseInt(this.div.style.height);
- }
- },
-
- /**
- * @return {OpenLayers.LonLat}
- */
- getCenter: function () {
- return this.center;
- },
-
- /**
- * @return {OpenLayers.Bounds}
- */
- getExtent: function () {
- if (this.center) {
- var res = this.getResolution();
- var size = this.getSize();
- var w_deg = size.w * res;
- var h_deg = size.h * res;
- return new OpenLayers.Bounds(
- this.center.lon - w_deg / 2,
- this.center.lat - h_deg / 2,
- this.center.lon + w_deg / 2,
- this.center.lat + h_deg / 2);
- } else {
- return null;
- }
- },
-
- /**
- * @return {OpenLayers.Bounds}
- */
- getFullExtent: function () {
- return this.maxExtent;
- },
-
- getZoomLevels: function() {
- return this.maxZoomLevel;
- },
-
- /**
- * @param {OpenLayers.Bounds} bounds
- *
- * @return {int}
- */
- getZoomForExtent: function (bounds) {
- var size = this.getSize();
- var width = bounds.getWidth();
- var height = bounds.getHeight();
- var deg_per_pixel = (width > height ? width / size.w : height / size.h);
- var zoom = Math.log(this.maxResolution / deg_per_pixel) / Math.log(2);
- return Math.floor(Math.min(Math.max(zoom, 0), this.getZoomLevels()));
- },
-
- /**
- * @param {OpenLayers.Pixel} layerPx
- *
- * @returns px translated into view port pixel coordinates
- * @type OpenLayers.Pixel
- * @private
- */
- getViewPortPxFromLayerPx:function(layerPx) {
- var viewPortPx = layerPx.copyOf();
-
- viewPortPx.x += parseInt(this.layerContainerDiv.style.left);
- viewPortPx.y += parseInt(this.layerContainerDiv.style.top);
-
- return viewPortPx;
- },
-
- /**
- * @param {OpenLayers.Pixel} viewPortPx
- *
- * @returns px translated into view port pixel coordinates
- * @type OpenLayers.Pixel
- * @private
- */
- getLayerPxFromViewPortPx:function(viewPortPx) {
- var layerPx = viewPortPx.copyOf();
-
- layerPx.x -= parseInt(this.layerContainerDiv.style.left);
- layerPx.y -= parseInt(this.layerContainerDiv.style.top);
-
- return layerPx;
- },
-
-
- /**
- * @param {OpenLayers.Pixel} px
- *
- * @return {OpenLayers.LonLat}
- */
- getLonLatFromLayerPx: function (px) {
- //adjust for displacement of layerContainerDiv
- px = this.getViewPortPxFromLayerPx(px);
- return this.getLonLatFromViewPortPx(px);
- },
-
- /**
- * @param {OpenLayers.Pixel} viewPortPx
- *
- * @returns An OpenLayers.LonLat which is the passed-in view port
- * OpenLayers.Pixel, translated into lon/lat given the
- * current extent and resolution
- * @type OpenLayers.LonLat
- * @private
- */
- getLonLatFromViewPortPx: function (viewPortPx) {
- var center = this.getCenter(); //map center lon/lat
- var res = this.getResolution();
- var size = this.getSize();
-
- var delta_x = viewPortPx.x - (size.w / 2);
- var delta_y = viewPortPx.y - (size.h / 2);
-
- return new OpenLayers.LonLat(center.lon + delta_x * res ,
- center.lat - delta_y * res);
- },
-
- // getLonLatFromPixel is a convenience function for the API
- /**
- * @param {OpenLayers.Pixel} pixel
- *
- * @returns An OpenLayers.LonLat corresponding to the given
- * OpenLayers.Pixel, translated into lon/lat using the
- * current extent and resolution
- * @type OpenLayers.LonLat
- */
- getLonLatFromPixel: function (px) {
- return this.getLonLatFromViewPortPx(px);
- },
-
- /**
- * @param {OpenLayers.LonLat} lonlat
- *
- * @returns An OpenLayers.Pixel which is the passed-in OpenLayers.LonLat,
- * translated into layer pixels given the current extent
- * and resolution
- * @type OpenLayers.Pixel
- */
- getLayerPxFromLonLat: function (lonlat) {
- //adjust for displacement of layerContainerDiv
- var px = this.getViewPortPxFromLonLat(lonlat);
- return this.getLayerPxFromViewPortPx(px);
- },
-
- /**
- * @param {OpenLayers.LonLat} lonlat
- *
- * @returns An OpenLayers.Pixel which is the passed-in OpenLayers.LonLat,
- * translated into view port pixels given the current extent
- * and resolution
- * @type OpenLayers.Pixel
- * @private
- */
- getViewPortPxFromLonLat: function (lonlat) {
- var resolution = this.getResolution();
- var extent = this.getExtent();
- return new OpenLayers.Pixel(
- Math.round(1/resolution * (lonlat.lon - extent.left)),
- Math.round(1/resolution * (extent.top - lonlat.lat))
- );
- },
-
- // getLonLatFromPixel is a convenience function for the API
- /**
- * @param {OpenLayers.LonLat} lonlat
- *
- * @returns An OpenLayers.Pixel corresponding to the OpenLayers.LonLat
- * translated into view port pixels using the current extent
- * and resolution
- * @type OpenLayers.Pixel
- */
- getPixelFromLonLat: function (lonlat) {
- return this.getViewPortPxFromLonLat(lonlat);
- },
-
- /**
- * @param {OpenLayers.LonLat} lonlat
- * @param {int} zoom
- */
- setCenter: function (lonlat, zoom, minor) {
- if (this.center) { // otherwise there's nothing to move yet
- this.moveLayerContainer(lonlat);
- }
- this.center = lonlat.copyOf();
- var zoomChanged = null;
- if (zoom != null && zoom != this.zoom
- && zoom >= 0 && zoom <= this.getZoomLevels()) {
- zoomChanged = (this.zoom == null ? 0 : this.zoom);
- this.zoom = zoom;
- }
-
- if (!minor) this.events.triggerEvent("movestart");
- this.moveToNewExtent(zoomChanged, minor);
- if (!minor) this.events.triggerEvent("moveend");
- },
-
- /**
- * ZOOM TO BOUNDS FUNCTION
- * @private
- */
- moveToNewExtent: function (zoomChanged, minor) {
- if (zoomChanged != null) { // reset the layerContainerDiv's location
- this.layerContainerDiv.style.left = "0px";
- this.layerContainerDiv.style.top = "0px";
-
- //redraw popups
- for (var i = 0; i < this.popups.length; i++) {
- this.popups[i].updatePosition();
- }
-
- }
- var bounds = this.getExtent();
- for (var i = 0; i < this.layers.length; i++) {
- this.layers[i].moveTo(bounds, (zoomChanged != null), minor);
- }
- this.events.triggerEvent("move");
- if (zoomChanged != null)
- this.events.triggerEvent("zoomend",
- {oldZoom: zoomChanged, newZoom: this.zoom});
- },
-
- /**
- * zoomIn
- * Increase zoom level by one.
- * @param {int} zoom
- */
- zoomIn: function() {
- if (this.zoom != null && this.zoom <= this.getZoomLevels()) {
- this.zoomTo( this.zoom += 1 );
- }
- },
-
- /**
- * zoomTo
- * Set Zoom To int
- * @param {int} zoom
- */
- zoomTo: function(zoom) {
- if (zoom >= 0 && zoom <= this.getZoomLevels()) {
- var oldZoom = this.zoom;
- this.zoom = zoom;
- this.moveToNewExtent(oldZoom);
- }
- },
-
- /**
- * zoomOut
- * Decrease zoom level by one.
- * @param {int} zoom
- */
- zoomOut: function() {
- if (this.zoom != null && this.zoom > 0) {
- this.zoomTo( this.zoom - 1 );
- }
- },
-
- /**
- * zoomToFullExtent
- * Zoom to the full extent and recenter.
- */
- zoomToFullExtent: function() {
- var fullExtent = this.getFullExtent();
- this.setCenter(
- new OpenLayers.LonLat((fullExtent.left+fullExtent.right)/2,
- (fullExtent.bottom+fullExtent.top)/2),
- this.getZoomForExtent(fullExtent)
- );
- },
-
- /**
- * @param {OpenLayers.LonLat} lonlat
- * @private
- */
- moveLayerContainer: function (lonlat) {
- var container = this.layerContainerDiv;
- var resolution = this.getResolution();
-
- var deltaX = Math.round((this.center.lon - lonlat.lon) / resolution);
- var deltaY = Math.round((this.center.lat - lonlat.lat) / resolution);
-
- var offsetLeft = parseInt(container.style.left);
- var offsetTop = parseInt(container.style.top);
-
- container.style.left = (offsetLeft + deltaX) + "px";
- container.style.top = (offsetTop - deltaY) + "px";
- },
-
- CLASS_NAME: "OpenLayers.Map"
-};