OpenLayers源码学习15:地图Map_1 Posted on 2015-02-28 | In OpenLayers学习 | 年后上班了, 这年过的比较累 各种串门…这个map类估计一次看不完, 分几次慢慢看吧 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178//OpenLayers.Map的实例, 注释说此类中只有必要方法(其实三千行...), 还需要配合OpenLayers.Control对地图进行操作OpenLayers.Map = OpenLayers.Class({ //不同class的z-index配置 Z_INDEX_BASE: { BaseLayer: 100, Overlay: 325, Feature: 725, Popup: 750, Control: 1000 }, /** * Register a listener for a particular event with the following syntax: * (code) * map.events.register(type, obj, listener); * (end) * * 支持的map事件类型: * preaddlayer ,addlayer ,preremovelayer ,removelayer ,changelayer, movestart * move,moveend,zoomend, mouseover, mouseout, mousemove, changebaselayer, updatesize */ //map的唯一id id: null, //分数zoom值, base layer是否支持分数zoom值 fractionalZoom: false, //map对象持有的OpenLayers.Events实例 events: null, //如果为true, 绘制过程中最底层的layer就变成base layer了 allOverlays: false, //map的包裹div, 应该在构造函数里指定 或者用render方法(如果调用render就不能用<maxResolution> auto, 必须指定) div: null, //map当前是否正在被拖拽标志 dragging: false, //当前map对象的 this.div{<OpenLayers.Size>} size: null, //map的viewport viewPortDiv: null, // 在zoom后图层容器的lonlat layerContainerOrigin: null, //图层的容器div layerContainerDiv: null, // <OpenLayers.Layer>的数组 layers: null, // <OpenLayers.Control>数组, 如果没在构造里指定, 则默认有 /* - <OpenLayers.Control.Navigation> or <OpenLayers.Control.TouchNavigation> * - <OpenLayers.Control.Zoom> or <OpenLayers.Control.PanZoom> * - <OpenLayers.Control.ArgParser> * - <OpenLayers.Control.Attribution> */ controls: null, //<OpenLayers.Popup>数组 popups: null, //当前选择的base layer<OpenLayers.Layer> baseLayer: null, //缓存地图中心点<OpenLayers.LonLat> center: null, //缓存分辨率 resolution: null, //缓存zoom值 zoom: 0, // 当前extent和panning的比值 panRatio: 1.5, //缓存options对象(只读), 通过构造传进来 options: null, // Options //瓦片尺寸 <OpenLayers.Size> tileSize: null, //默认投影是经纬度, 用其他投影如墨卡托需要设置maxExtent, maxResolution. //投影由当前的baseLayer决定(see <baseLayer> and <getProjectionObject>). projection: "EPSG:4326", //单位 'degrees' (or 'dd'), 'm', 'ft', 'km', 'mi', 'inches'. units: null, //分辨率数组(map units per pixel) resolutions: null, //最大分辨率 maxResolution: null, //最小分辨率 minResolution: null, //最大缩放 maxScale: null, //最小缩放 minScale: null, // 最大范围. 如果是数组 则顺序为(left, bottom, right, top) , 否则是<OpenLayers.Bounds> maxExtent: null, //最小范围 minExtent: null, // 受限范围, 地图中心点将会被限制在此范围内. 要是想限制zoom的分辨率要用maxResolution restrictedExtent: null, // zoom等级数 numZoomLevels: 16, //css风格 theme: null, // 显示投影<OpenLayers.Projection> displayProjection: null, /** * APIProperty: tileManager * {<OpenLayers.TileManager>|Object} By default, and if the build contains * TileManager.js, the map will use the TileManager to queue image requests * and to cache tile image elements. To create a map without a TileManager * configure the map with tileManager: null. To create a TileManager with * non-default options, supply the options instead or alternatively supply * an instance of {<OpenLayers.TileManager>}. */ // 是否把map接收的事件继续传递到当前页面上. 默认接收完阻止掉 fallThrough: false, // resize事件触发时, 是否重新调整map的大小 autoUpdateSize: true, // 随构造传入的监听器会被注册到<OpenLayers.Events.on> eventListeners: null, // 移动中心点后的<OpenLayers.Tween>动画对象see panTo(), 这个动画之前没看 panTween: null, //移动中心点时候的动画, "null"可以关掉动画 panMethod: OpenLayers.Easing.Expo.easeOut, //动画步长参数 panDuration: 50, //zoom时候的动画策略 <OpenLayers.Tween> zoomTween: null, //缩放动画 zoomMethod: OpenLayers.Easing.Quad.easeOut, //zoom动画持续步长 zoomDuration: 20, //气泡外围的padding值 paddingForPopups : null, // 图层容器得起始位置px layerContainerOriginPx: null, //最下最左值 , maxExtent和viewport的像素空隙 x,y minPx: null, //最顶最右值 , maxExtent和viewport的像素空隙 x,y maxPx: null, 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210/** * 创建一个新<OpenLayers.Map>实例 * * 参数: * div - {DOMElement|String} 地图所处div或div的id * options - {Object} 配置对象 * * 可以包含以下参数: * center - {<OpenLayers.LonLat>|Array} 地图中心点 * zoom - {Number} 默认zoom值 * extent - {<OpenLayers.Bounds>|Array} 初始化范围, center和zoom指定的话这个就无效了 * * 代码示例: * var map = new OpenLayers.Map({ * div: "map_id", * projection: "EPSG:3857", * maxExtent: [-18924313.432222, -15538711.094146, 18924313.432222, 15538711.094146], * restrictedExtent: [-13358338.893333, -9608371.5085962, 13358338.893333, 9608371.5085962], * center: [-12356463.476333, 5621521.4854095] * }); * * //没给中心点, 需要创建完再render一下 * var map = new OpenLayers.Map({ * projection: "EPSG:3857", * maxExtent: new OpenLayers.Bounds(-200000, -200000, 200000, 200000) * }); */ initialize: function (div, options) { //就一个参数的情况, 就像示例1. div实际上是参数对象的"div"项 if(arguments.length === 1 && typeof div === "object") { options = div; div = options && options.div; } //读取OpenLayers.Map.里的配置项 this.tileSize = new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH, OpenLayers.Map.TILE_HEIGHT); //默认气泡的padding是15 this.paddingForPopups = new OpenLayers.Bounds(15, 15, 15, 15); //默认css风格 this.theme = OpenLayers._getScriptLocation() + 'theme/default/style.css'; //缓存最原始的options, 用Util.extend闭包缓存 this.options = OpenLayers.Util.extend({}, options); //覆盖掉this里的默认配置 OpenLayers.Util.extend(this, options); //查询到projCode var projCode = this.projection instanceof OpenLayers.Projection ? this.projection.projCode : this.projection; OpenLayers.Util.applyDefaults(this, OpenLayers.Projection.defaults[projCode]); //最大 最小 受限范围, 统一处理<OpenLayers.Bounds>或数组 if (this.maxExtent && !(this.maxExtent instanceof OpenLayers.Bounds)) { this.maxExtent = new OpenLayers.Bounds(this.maxExtent); } if (this.minExtent && !(this.minExtent instanceof OpenLayers.Bounds)) { this.minExtent = new OpenLayers.Bounds(this.minExtent); } if (this.restrictedExtent && !(this.restrictedExtent instanceof OpenLayers.Bounds)) { this.restrictedExtent = new OpenLayers.Bounds(this.restrictedExtent); } if (this.center && !(this.center instanceof OpenLayers.LonLat)) { this.center = new OpenLayers.LonLat(this.center); } //准备一个新数组 this.layers = []; //唯一id this.id = OpenLayers.Util.createUniqueID("OpenLayers.Map_"); //map需要绑定的dom元素 this.div = OpenLayers.Util.getElement(div); if(!this.div) { this.div = document.createElement("div");//没找到dom的创建一个, 宽高为1 this.div.style.height = "1px"; this.div.style.width = "1px"; } OpenLayers.Element.addClass(this.div, 'olMap'); //viewpoint是div里最外层的 var id = this.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.viewPortDiv.className = "olMapViewport"; this.div.appendChild(this.viewPortDiv);//在map需要绑定的div里内层直接套viewport //给this(新的map实例)绑定事件: 接收事件的对象是viewPort 监听事件暂时为空 this.events = new OpenLayers.Events( this, this.viewPortDiv, null, this.fallThrough, {includeXY: true} ); //瓦片管理, 这个没看 if (OpenLayers.TileManager && this.tileManager !== null) { if (!(this.tileManager instanceof OpenLayers.TileManager)) { this.tileManager = new OpenLayers.TileManager(this.tileManager); } this.tileManager.addMap(this); } // 续写一个id, 根据此唯一id创建一个div id = this.id + "_OpenLayers_Container"; this.layerContainerDiv = OpenLayers.Util.createDiv(id); this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;//比气泡z-index少1 this.layerContainerOriginPx = {x: 0, y: 0}; this.applyTransform(); this.viewPortDiv.appendChild(this.layerContainerDiv); this.updateSize(); //如果传入eventListeners对象的话, 就都on一下 if(this.eventListeners instanceof Object) { this.events.on(this.eventListeners); } if (this.autoUpdateSize === true) { // 如果autoUpdateSize配置为true的话, 增加一个窗口的'resize'事件的监听 this.updateSizeDestroy = OpenLayers.Function.bind(this.updateSize, this); OpenLayers.Event.observe(window, 'resize', this.updateSizeDestroy); } // 设置css风格的话 if(this.theme) { // 检查是否已有相等的url var addNode = true; var nodes = document.getElementsByTagName('link'); for(var i=0, len=nodes.length; i<len; ++i) { if(OpenLayers.Util.isEquivalentUrl(nodes.item(i).href, this.theme)) { addNode = false; break; } } // 需要把设置的风格url字串写入新的css外链元素, 而后去加载 if(addNode) { var cssNode = document.createElement('link'); cssNode.setAttribute('rel', 'stylesheet'); cssNode.setAttribute('type', 'text/css'); cssNode.setAttribute('href', this.theme); document.getElementsByTagName('head')[0].appendChild(cssNode); } } //没传入控件, 默认的控件 if (this.controls == null) { this.controls = []; if (OpenLayers.Control != null) { //在此之前已经加载过OpenLayers.Control //导航控件 if (OpenLayers.Control.Navigation) { this.controls.push(new OpenLayers.Control.Navigation()); } else if (OpenLayers.Control.TouchNavigation) { this.controls.push(new OpenLayers.Control.TouchNavigation()); } //zoom控件 if (OpenLayers.Control.Zoom) { this.controls.push(new OpenLayers.Control.Zoom()); } else if (OpenLayers.Control.PanZoom) { this.controls.push(new OpenLayers.Control.PanZoom()); } //url解析控件 if (OpenLayers.Control.ArgParser) { this.controls.push(new OpenLayers.Control.ArgParser()); } //给图层增加属性的控件 if (OpenLayers.Control.Attribution) { this.controls.push(new OpenLayers.Control.Attribution()); } } } //遍历控件添加到map for(var i=0, len=this.controls.length; i<len; i++) { this.addControlToMap(this.controls[i]); } this.popups = []; //销毁事件 this.unloadDestroy = OpenLayers.Function.bind(this.destroy, this); // 窗口关闭时调用销毁事件 OpenLayers.Event.observe(window, 'unload', this.unloadDestroy); // 初始化layers if (options && options.layers) { //运行顺序问题先删掉中心点和zoom delete this.center; delete this.zoom; this.addLayers(options.layers); //都添加完layers之后再set中心点+zoom if (options.center && !this.getCenter()) { this.setCenter(options.center, options.zoom); } } //默认的移动和zoom方法 if (this.panMethod) { this.panTween = new OpenLayers.Tween(this.panMethod); } if (this.zoomMethod && this.applyTransform.transform) { this.zoomTween = new OpenLayers.Tween(this.zoomMethod); } },