1.ol.interaction.Pointer
是管理地圖down、move、up事件的基類,也用於管理地圖拖拽事件。
構造函數結構如下:
new ol.interaction.Pointer(opt_options)
options包括的屬性有:
handleDownEvent:處理地圖的down事件。如果該事件返回true,drag隊列開始執行。
handleDragEvent:處理地圖的drag事件。當down事件返回true,鼠標在拖拽過程中該事件一直被觸發。
handleEvent:當地圖通知瀏覽器觸發交互時調用該函數,通過返回FALSE,可終止其他交互事件的傳播。
handleMoveEvent:在拖拽的過程中觸發move事件。
handleUpEvent:捕獲鼠標up事件。
2.updateWhileAnimating和updateWhileInteracting屬性
默認情況下,當在和地圖交互或者動畫過程中,tile和vector圖層會等待這些過程執行完后才會更新。我們可以通過兩個屬性禁止這樣的現象,在vector圖層中,必須在layer級別控制。而像tiled圖層可以直接通過map級別控制。代碼如下:
var map = new ol.Map({ target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.TileWMS({ url: 'http://demo.opengeo.org/geoserver/wms', params: { layers: 'ne_50m_land', format: 'image/png' }, wrapX: false }), name: 'Natural Earth Land' }), new ol.layer.Vector({ source: new ol.source.Vector({ format: new ol.format.GeoJSON({ defaultDataProjection: 'EPSG:4326' }), url: '../../res/world_countries.geojson', wrapX: false }), name: 'World Countries', headers: { pop_est: 'integer', gdp_md_est: 'integer' }, type: 'polygon', updateWhileAnimating: false, updateWhileInteracting: false }) ], view: new ol.View({ center: [0, 0], zoom: 2, extent: ol.proj.get('EPSG:3857').getExtent() }), loadTilesWhileAnimating: true, loadTilesWhileInteracting: true });
3.限制地圖大小屬性
只要繼承至ol.layer.Base對象的圖層都可通過wrapX:false限制圖層在x軸方向重復;另外也可通過設置view的extend屬性。
wrapX限制
var map = new ol.Map({ […] new ol.layer.Tile({ source: new ol.source.TileWMS({ […] wrapX: false […] new ol.layer.Vector({ source: new ol.source.Vector({ […] wrapX: false }),
extent顯示
view: new ol.View({ […] extent: ol.proj.get('EPSG:3857').getExtent() }),
4.分辨率resolution運算
在web地圖中,分辨率表示一個像素點表示的單位長度。下面通過一個計算中心點的例如來說明resolution的運算。
map.getView().on('propertychange', function (evt) { var projExtent = this.getProjection().getExtent(); if (projExtent) { var currentCenter = this.getCenter(); var currentResolution = this.getResolution(); var mapSize = map.getSize(); var newExtent = [projExtent[0] + currentResolution * mapSize[0] / 2, projExtent[1] + currentResolution * mapSize[1] / 2, projExtent[2] - currentResolution * mapSize[0] / 2, projExtent[3] - currentResolution * mapSize[1] / 2]; if (!(new ol.geom.Point(currentCenter).intersectsExtent(newExtent))) { currentCenter[0] = Math.min(Math.max(currentCenter[0], newExtent[0]), newExtent[2]); currentCenter[1] = Math.min(Math.max(currentCenter[1], newExtent[1]), newExtent[3]); this.setCenter(currentCenter); } } });
說明:上面是view各個屬性發生變化時觸發的事件,view.getProjection()獲取投影系對象proj,proj.getExtent()獲取投影系的邊界。view.getResolution()獲取當前視圖的分辨率,currentResolution*mapSize[0]表示整個視圖在經度方向的總長度。geom.intersectsExtent判斷geom是否在extent邊界總。
5.使用unByKey注銷事件
在很多ol.control.Control控件中我們會注冊一些事件,但經常忽略注銷,下面的方式是比較通用的注銷事件方式:
ol.control.NavigationHistory.prototype.setMap = function (map) { ol.control.Control.prototype.setMap.call(this, map); if (map === null) { ol.Observable.unByKey(this.get('eventId')); } else { this.set('eventId', map.on('moveend', function (evt) { if (this.get('shouldSave')) { var view = map.getView(); var viewStatus = { center: view.getCenter(), resolution: view.getResolution(), rotation: view.getRotation() }; var historyArray = this.get('history'); var currIndex = this.get('index'); historyArray.splice(currIndex + 1, historyArray.length - currIndex - 1); if (historyArray.length === this.get('maxSize')) { historyArray.splice(0, 1); } else { currIndex += 1; } historyArray.push(viewStatus); this.set('index', currIndex); } else { this.set('shouldSave', true); } }, this)); } };
當控件和地圖分離時,map會被設置為null,這個時候可調用ol.Observable.unByKey方法取消對事件的監聽。
6.如何改變地圖的投影系
首先要創建一個新的視圖View,設置view的center、zoom、projection、extent屬性。然后調用map的setView重新替換地圖的視圖。
var view = _this.getMap().getView(); var oldProj = view.getProjection(); var newProj = ol.proj.get(this.value); var newView = new ol.View({ center: ol.proj.transform(view.getCenter(), oldProj, newProj), zoom: view.getZoom(), projection: newProj, extent: newProj.getExtent() }); _this.getMap().setView(newView);
其次需要替換所有圖層的投影系,遍歷所有的圖層,按照圖層的類型采用不同的替換方式。
_this.getMap().getLayers().forEach(function (layer) { _this.changeLayerProjection(layer, oldProj, newProj); });
這里的changeLayerProjection是自定義的一個函數,用來處理當個圖層的坐標系。
ol.control.Projection.prototype.changeLayerProjection = function (layer, oldProj, newProj) { if (layer instanceof ol.layer.Group) { layer.getLayers().forEach(function (subLayer) { this.changeLayerProjection(subLayer, oldProj, newProj); }); } else if (layer instanceof ol.layer.Tile) { var tileLoadFunc = layer.getSource().getTileLoadFunction(); layer.getSource().setTileLoadFunction(tileLoadFunc); } else if (layer instanceof ol.layer.Vector) { var features = layer.getSource().getFeatures(); for (var i = 0; i < features.length; i += 1) { features[i].getGeometry().transform(oldProj, newProj); } } };
layer存在多種類型,所有需要判斷類型分別處理。如果是ol.layer.Group類型,則繼續遍歷分組中的每個圖層;如果圖層類型為ol.layer.Tile瓦片類型,這需要getTileLoadFunction獲取加載函數,重新設置下(由於瓦片圖層有緩存,如果不重新設置加載方式,瓦片圖層還是會從老的坐標系加載瓦片,通過setTileLoadFunction重新設置下加載函數可清理掉瓦片緩存);如果圖層類型為ol.layer.Vector,需要遍歷source中的所有feature,調用feature下geometry的tranform把老坐標系的坐標轉換為新坐標系的坐標。
7.openlayers三種渲染方式
DOM渲染
DOM渲染是一種支持預THML5瀏覽器的傳統渲染方式。主要限制在於不能顯示vector圖層,因為vector圖層是使用canvas渲染的。僅僅tile和image圖層能被DOM元素創建。如果必須支持傳統的瀏覽器(不支持canvas),那么openlayers 2是一個不錯的選擇。
Canvas渲染
是openlayers 3默認的渲染方式,每個圖層畫在單獨的canvas元素上。
WEBGL
WEBGL是瀏覽器對OpenGL的一個現實,瀏覽器有能力使用硬件加速渲染。該技術廣泛用在3D客戶端應用。
8.導出圖層的必備參數
crossOrigin,ol.source.TileWMS的構造函數有一個參數叫做crossOrigin,如果我們想導出地圖圖片,必須要設置這個參數:
new ol.layer.Tile({ source: new ol.source.TileWMS({ url: 'http://demo.opengeo.org/geoserver/wms', params: { layers: 'nlcd', format: 'image/png' }, wrapX: false, crossOrigin: 'anonymous' }), name: 'Land Cover' })
9.WEBGL
https://webglfundamentals.org/
10.ol.Geolocation
獲取地理位置對象,一個HTML5的幫助類,提供HTML5 Geolocation功能。跟蹤終端設備的位置。例如:
var geoloc = new ol.Geolocation({ projection: map.getView().getProjection(), tracking: true }); var geoCaching = new ol.layer.Vector({ source: new ol.source.Vector() }); map.addLayer(geoCaching); geoloc.once('change:position', function (evt) { var altitude = this.getAltitude() || 100; var myPos = this.getPosition(); map.getView().setCenter(myPos); map.getView().setZoom(17); for (var i = 0; i < 50; i += 1) { geoCaching.getSource().addFeature(new ol.Feature({ geometry: new ol.geom.Point([myPos[0] - 500 + Math.random() * 1000, myPos[1] - 500 + Math.random() * 1000, altitude - 150 + Math.random() * 300]), loot: 'Treasures of the Seven Seas' })); } });
說明:geoloc不需要添加到地圖對象上,只需要設置投影系參數。如果想監聽實時位置,可注冊change: position事件。geoloc的getAltitude方法獲取海拔高度。
Geolocation對象除projection、tracking參數外,還有一個trackingOptions參數,可設置如下:
var geoloc = new ol.Geolocation({ projection: map.getView().getProjection(), tracking: true, trackingOptions: { enableHighAccuracy: true, maximumAge: 2000 } });
enableHighAccuracy允許高精准定位,maximumAge設置定位間隔時間,單位為毫秒。
11.Openlayers 3 shp插件使用
shp插件支持導入shp文件到openlayers上直接展示。代碼如下:
layerTree.prototype.addVectorLayer = function (form) { var file = form.file.files[0]; var currentProj = this.map.getView().getProjection(); var fr = new FileReader(); var sourceFormat = new ol.format.GeoJSON(); var source = new ol.source.Vector(); fr.onload = function (evt) { var vectorData = evt.target.result; var dataProjection = form.projection.value || sourceFormat.readProjection(vectorData) || currentProj; shp(vectorData).then(function (geojson) { source.addFeatures(sourceFormat.readFeatures(geojson, { dataProjection: dataProjection, featureProjection: currentProj })); }); }; fr.readAsArrayBuffer(file); var layer = new ol.layer.Vector({ source: source, name: form.displayname.value }); this.addBufferIcon(layer); this.map.addLayer(layer); this.messages.textContent = 'Vector layer added successfully.'; return this; };
12.ol.style.Icon
如何定位圖標,參考下面代碼:
style: new ol.style.Style({ image: new ol.style.Icon({ /*anchor: [0.5, 46], anchorXUnits: 'fraction', anchorYUnits: 'pixels',*/ src: '../../res/marker.png' }) })
13.Cesium使用
openlayers團隊封裝了ol3cesium js庫,ol3cesium包含了ol.js代碼,所有我們在使用ol3cesium的時候不用再引用ol.js了。例如:
<script type="text/javascript" src="../../js/ol3-cesium- 1.10.0/Cesium/Cesium.js"></script> <script type="text/javascript" src="../../js/ol3-cesium- 1.10.0/ol3cesium.js"></script>
如果我們自定義了ol.js,我們可以在ol3cesium.js引用的后面再引用ol.js即可。例如:
<script type="text/javascript" src="../../js/ol3-cesium-1.10.0/ol3cesium.js"></script> <script type="text/javascript" src="../../ol/ol.js"></script>
Cesium場景的可視化非常智能,我們僅僅需要額外定義一個海拔瓦圖源即可。創建代碼如下:
setTimeout(function () { var ol3d = new olcs.OLCesium({map: _this.getMap()}); var scene = ol3d.getCesiumScene(); scene.terrainProvider = new Cesium.CesiumTerrainProvider({ url: 'http://assets.agi.com/stk-terrain/world' }); _this.set('cesium', ol3d); }, 0);
可調用cesium.setEnabled方法設置是否可用,setBlockCesiumRendering方法設置是否在后台渲染。 可通過這兩個方法在2D和3D之間切換。
controlButton.addEventListener('click', function (evt) { var cesium = _this.get('cesium'); if (cesium.getEnabled()) { cesium.setBlockCesiumRendering(true); cesium.setEnabled(false); } else { cesium.setBlockCesiumRendering(false); cesium.setEnabled(true); } });
14.openlayers 編譯環境
phtyon必須是2.*的版本,並且配置PYTHON環境變量