openlayers是一個高性能、功能全面的地圖庫。有如下特性:javascript
通常來講google map api就知足需求了,可是當須要在地圖上繪製大量節點時,使用svg來顯示部件就會出現很嚴重的性能問題,通常狀況下google maps等的編輯操做也不夠流暢。而openlayers使用canvas做爲矢量層,大量的點線面信息對於canvas的影響是較小的,並且canvas的交互也更加流暢。css
針對以上幾點,以爲本身的小經驗會對你們有所幫助,能夠少走些彎路,也是對本身這幾天工做的一個總結。html
下面經過一個簡單地小例子介紹openlayers的一些基本用法,以及我以爲重要的地方。java
須要使用google map或者高德地圖做爲底圖,在地圖上繪製一個矩形,實現矩形的編輯而且可以獲得矩形被修改以後的回調函數。大概會涉及到這些技術點:jquery
附上簡單截圖ajax
咱們但願openlayer能和google map等組合使用,可是因爲google等地圖廠商不肯意向openlayer「妥協」,所以如今沒法直接使用Tiled Layers
,但咱們能夠將openlayer與地圖api組合起來使用。bootstrap
只使用地圖的底圖,在底圖上覆蓋一層 openlayer 的 canvas 層來顯示數據並攔截與底圖之間的交互,經過地圖的 api 來重設狀態。
此方案還有如下優勢:canvas
代碼以下:api
html<!DOCTYPE html> <html> <head> <title>Snap interaction example</title> <script src="https://code.jquery.com/jquery-1.11.2.min.js"></script> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.6.0/ol.css" type="text/css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.6.0/ol.js"></script> <script src="https://maps.googleapis.com/maps/api/js"></script> <style type="text/css"> div.fill { width: 100%; height: 100%; } .map { width: 800px; height: 400px; } </style> </head> <body> <div class="container-fluid"> <div class="row-fluid"> <div class="span12"> <div id="map" class="map"> <!-- gmap用於加載google maps, olmap用於加載openlayer canvas。 目標是加載完畢以後olmap覆蓋與gmap之上而且攔截交互操做。 開始時放在同一層的好處是都能根據父節點來設置長寬。也能夠在js中動態生成div,渲染後插入 --> <div id="gmap" class="fill"></div> <div id="olmap" class="fill"></div> </div> </div> </div> </div> <script type="application/javascript"> // 加載google map並禁用地圖的交互操做 var gmap = new google.maps.Map(document.getElementById('gmap'), { disableDefaultUI: true, keyboardShortcuts: false, draggable: false, disableDoubleClickZoom: true, scrollwheel: false, streetViewControl: false }); // ol.View 是openlayers用於控制地圖的 座標系標準 zoom center rotate等操做的對象,在實例化map時候須要使用 var view = new ol.View({ // make sure the view doesn't go beyond the 22 zoom levels of Google Maps maxZoom: 21, projection: 'EPSG:4326' // 設置爲標準經緯度的座標標準,十分重要! 默認是'EPSG:3857' }); // view 拖動時觸發事件,根據當前的座標轉化爲經緯度,調用谷歌地圖setCenter方法同步地圖位置 view.on('change:center', function () { var center = view.getCenter(); gmap.setCenter(new google.maps.LatLng(center[1], center[0])); // 注意順序 }); // 同上,更改焦距時觸發的時間 view.on('change:resolution', function () { gmap.setZoom(view.getZoom()); }); // ol.source.Vector 做爲 ol.layer.Vector的數據集,增刪改feature的方法由source提供 var vectorSource = new ol.source.Vector(); var vector = new ol.layer.Vector({ source: vectorSource }); var olMapDiv = document.getElementById('olmap'); var map = new ol.Map({ layers: [vector], // 所使用的圖層 // 禁用掉默認的拖動、旋轉等交互 interactions: ol.interaction.defaults({ altShiftDragRotate: false, dragPan: false, rotate: false }).extend([new ol.interaction.DragPan({kinetic: null})]), target: olMapDiv, view: view // 這裏可使用 new ol.View({options}) 可是在這裏須要經過手動設置來觸發google maps調節到正確地zoom與center }); view.setCenter([10.689697265625, -25.0927734375]); // 若是未設置view的座標標準,這裏千萬要注意不要直接寫經緯度 view.setZoom(6); // 設置縮放等級 // 將openlayers容器放置到google地圖容器中 olMapDiv.parentNode.removeChild(olMapDiv); gmap.controls[google.maps.ControlPosition.TOP_LEFT].push(olMapDiv); </script> </body> </html>
有了這段代碼應該就有了一個能夠拖動縮放的地圖了。數組
固然光有一個地圖是不行的,若是須要往地圖上面添加feature怎麼辦呢?大體有如下兩種場景:
先上代碼
javascript/** * 將geoJson字符串解析後添加到地圖中 * @param vectorSource {ol.source.Vector} 須要添加feature的矢量層數據對象 * @param data {string} geoJson字符串 */ function addFeatures(vectorSource, data){ vectorSource.addFeatures(ol.format.GeoJSON.readFeatures(data, { // 數據的座標code dataProjection: 'EPSG:3857', // 地圖view使用的座標code featureProjection: 'EPSG:4326' })); }
ol.format
下有不少種數據類型,選擇匹配的數據格式。
好比WKT
使用ol.format.WKT.readFeature
readFeature
返回的是ol.Feature
的數組,能夠經過遍歷其來得到feature對象,從而按需求修改或者掛載監聽事件。
若是現有的數據是geoJson等標準格式的數據,能夠經過ol.format
中的類進行轉換。若是有需求則使用ol.proj.transform
進行座標系轉換。
// 返回單個feature對象 var feature = ol.format.GeoJSON.readFeature(data) // 添加到source vectorSource.addFeature(feature);
若是拿到的是經緯度信息,添加一個polygon
// data 是一個coordinates的二維數組 須要注意 var feature = new ol.feature(new ol.geom.Polygon(data));
介紹如何修改feature以及掛載監聽事件。
// 聲明選擇交互 var select = new ol.interaction.Select({ // 根據 feature editable 選項來判斷是否能夠選中 filter: function(feature) { if (_this._featureMap[feature.getId()].editable) { return true; } } }); // 獲得被選中元件的對象 var selected = select.getFeatures(); // 聲明修改交互,能夠修改被選中的feature var modify = new ol.interaction.Modify({ features: selected }); // 當新元件被選中時觸發 selected.on('add', event => { var feature = event.element }) // 當元件被取消選中時觸發,通常把元件的修改回調放在這 selected.on('remove', evt => { var feature = evt.element; var fid = feature.getId(); // 判斷元件是否被修改仍是須要feature的change事件 console.log(fid); }); // 在interactions中添加 this._map = new ol.Map({ layers: [vector], interactions: ol.interaction.defaults({ altShiftDragRotate: false, dragPan: false, rotate: false }).extend([new ol.interaction.DragPan({kinetic: null}), select, modify]), target: $olMapDiv, view: this._view });
通常來講若是須要後續對feature進行操做,可使用getId
方法拿到feature
的id
,能夠經過setId
來設置本身想要的id
,不然會自動生成。 將id
存在常駐的對象中供之後使用。
假設拿到ol.Feature
對象 feature
feature.on('change:geometry', function(e){ var feature = e.element; // do what you want 好比標記元件已被修改 })
須要注意的是這個onChange
事件在修改的過程當中會不斷地觸發,若是須要的是修改完成以後的回調,須要使用select
的remove
事件。
select.getFeatures().on('remove', function(e){})
設置id
feature.setId(id)
獲得geometry
對象
var geometry = feature.getGeometry(); // 經過調用geometry類的方法修改元件座標
feature to string
var format = new ol.format.GeoJSON(); format.writeFeature(feature);
'EPSG:3857'
,標準經緯度座標系是'EPSG:4326'
ol.proj.transform(coordinate, source, destination)
coordinate
在文檔中得類型是 Coordinate
其實就是一個有橫縱座標組成的數組,所以必定要注意官方文檔中得數據類型。source
當前座標編碼 string類型destination
目標座標編碼 string類型
ol.proj.fromLonLat(coordinate, opt_projection)
opt_projection
目標座標編碼 string類型
ol.proj.toLonLat(coordinate, opt_projection)
ol.format