前段時間幫助同事重構一個地圖類的項目,而後就學習了openLayer3這個框架,可是官網上沒有中文版,也沒有詳細的例子解釋,我只能遇到看不懂的就翻譯成中文來用,爲了方便之後再用這個ol,可以更快的上手,就花了幾天的時間總結了ol的知識,ol功能很豐富,API也不少,沒有寫太多,只是寫了怎麼用的,只要學會了根本,就能夠很快的使用API去操做map。
另外,在總結知識的同時,還寫了demo,加深本身的理解,你們以爲不錯的話,給個star~ GitHubjavascript
var map = new ol.Map({ target:'map', layers:[], view:views, interactions:interactions, controls:controls, })
map是openlayers的核心
組件,全部的操做方法以及渲染都是掛載到map上面。建立的map對象須要傳一個對象進去,最多見的就有如下幾個屬性,數據庫
* target --> 地圖的掛載元素,就是在html元素裏聲明的id * layers --> 層,是個數組,能夠放不少層,若是未定義,則將呈現沒有圖層的地圖,圖層是按照提供的順序渲染的,所以,若是您但願(例如)矢量圖層顯示在圖塊圖層的頂部,則它必須位於圖塊圖層以後。 * view --> map的視圖, * interactions --> 交互,好比鼠標事件致使放大,縮小,旋轉之類的,默認都是true * controls --> 控件,相似與按鈕,有放大,縮小,全屏等的按鈕
最簡單的顯示地圖:json
document.body.innerHTML = `<div id="map" style="height:400px;width:100%"></div>`; var map = new ol.Map({ target:'map', layers:[new ol.layers.Tile({ source: new ol.source.OSM() })], view: new ol.View({ center:[0,0], projection: 'EPSG:4326', zoom:10, }), interactions: ol.interaction.defaults({ doubleClickZoom:false, altShiftDragRotate:false }), controls: ol.control.defaults({ attribution: false, }) })
這個map不是裏面的Map,而是初始化後的map,map = new ol.Map()
;在openlayers3 的API中,有不少方法,能夠經過方法去操做layers,view,interactions,controls。
打印map,能夠發現map裏面有不少屬性,能夠簡單知道map上有多少個層,target是誰,size是多少等等,也能夠經過API方法去獲取api
var target = map.getTarget(); // 獲取 target的值 -- map var size = map.getSize(); // 獲取可視區域的寬高。
一樣的,也能夠在map上設置數組
map.addControl(new ol.control.FullScreen()); // 添加全屏控件 map.addLayers( new ol.layer.Vector({ source:new ol.Source.Vector() })) // 添加一個矢量圖層
*map裏有一個函數方法,能夠經過點擊某個圖層或某個點而獲取到當前的層和信息。
forEachFeatureAtPixel
(pixel, callback, opt_options)
params: pixel:座標
callback:回調函數,將使用兩個參數調用回調,第一個是feature,第二個是layers
opt_options:可選
map.on('click',function(e){ var feature = map.forEachFeatureAtPixel(e.pixel,function(f){ return f; }) console.log(feature); // ol.Feature })
視圖
.View對象表示地圖的簡單2D視圖。這是用於更改地圖的中心,分辨率和旋轉的對象。
一個視圖是由三種狀態肯定:center,resolution,zoom和rotation。每一個狀態具備相應的獲取和設置。
ol.proj.transform(coordinates,'EPSG:4326','EPSG:3857')
ol.proj.transform(coordinates,'EPSF:3857','EPSG:4326')
var view = new ol.View({ center:[104.06,30.67], projection:'EPSG:4326', // center: ol.proj.transform([104.06,30,67],'EPSG:4326','EPSG:3857'); // 這個和上面的結合體。 zoom:10, rotation:Math.PI/10, })
視圖對應的也有get和set系列的方法,用於獲取和設置zoom,center,rotation等等,除此以外,還有約束方法,constrainRotation(),約束旋轉度,API上有詳細解釋。
map.getView() // 就是當前視圖,view view.getZoom() // 獲取縮放級別; view.getCenter() // 獲取初始中心座標 view.setCenter([20,30]) // 設置初始中心[20,30],也能夠用ol.proj.transform view.constrainRotation(2,5) // 獲取此視圖的約束旋轉
層,是一個對象數組,將那些與數據顯示方式相關的屬性組合在一塊兒,造成一個層,openlayer就是由一個一個的層造成的,包括地圖,瓦片地圖,圖片,圖形都是由layer造成而呈如今map上的
簡單的來講,layer能夠是一個地圖,也能夠是一個圖形,也能夠是個圖片,由於是個數組,能夠互相疊加的,[map,image,shape],在相同位置的狀況下,後者會覆蓋前者。
根據這個圖片可知,layers有三種形式
每一個形式都須要一個source,數據源,因此每個形式都對應一個數據源,Source和Layer是一對一的關係,有一個Source,必然須要一個Layer,而後把這個Layer添加到Map上,就能夠顯示出來了。
對於瓦片數據源,也有不少屬性,
source
有不少形式,var OSMtile = new ol.layer.Tile({ source:new ol.source.OSM() }) var qqTile = new ol.layer.Tile({ source: new ol.source.XYZ({ url: 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}' }), }) map.addLayer(OSMtile); // 添加open street Map做爲底圖 map.addLayer(qqTile) // 添加騰訊地圖
map.addLayer()這個方法就至關於初始化中的layers的數組中添加同樣,以下代碼,這倆是等價的,只不事後者更靈活些。
var map = new ol.Map({ layers:[OSMtile,qqTile] }) // 等價於下面 map.addLayer(OSMtile); map.addLayer(qqTile)
ps!當添加地圖做爲底圖時,會發現騰訊底圖覆蓋率OSM地圖,是由於layer是一個數組,遵遁先來先渲染,後來居上的原則。
layer也有get/set方法,用來設置或獲取屬性,其實經過API就能夠知道響應方法去操做。
關於靜態圖片層,運用的很少,通常做爲寫死的,不常常換的實例中。
一樣,ol.layer.Image也有數據源,通常就是ol.source.ImageStatic,ol.source.ImageCanvas等等。
var center = ol.proj.transform([104.06667, 30.66667], 'EPSG:4326', 'EPSG:3857'); // 計算靜態圖映射到地圖上的範圍,圖片像素爲 550*344,保持比例的狀況下,把分辨率放大一些 var extent = [center[0]- 550*1000/2, center[1]-344*1000/2, center[0]+550*1000/2, center[1]+344*1000/2]; var imageStatic = new ol.layer.Image({ source: new ol.source.ImageStatic({ url: '../pandaBase.jpg', // 靜態圖 imageExtent: extent // 映射到地圖的範圍 }) }) map.addLayer(imageStatic);
矢量圖層,是用來渲染矢量數據的圖層類型,在OpenLayers裏,它是能夠定製的,能夠控制它的透明度,顏色,以及加載在上面的要素形狀等。經常使用於從數據庫中請求數據,接受數據,並將接收的數據解析成圖層上的信息。好比將鼠標移動到中國,相應的區域會以紅色高亮顯示出來,高亮即是矢量圖層的行爲
既然是個矢量圖,能夠改變大小,顏色,以及形狀。包含source數據源類,style類設置樣式,以及其餘的zIndex,opacity等等。
Feature類是Vector類用來在地圖上展現幾何對象,是Vector圖層類一個屬性。這個屬性是個*要素數組*。
對應的數據源ol.source.Vector也是個對象。最多見屬性的是features
和format
以及url
。一般url和format一塊,url按理傳來的是geojson格式的矢量圖,須要format格式化一下。最經常使用仍是features。
ol.Feature
feature名.getGeometry()
獲取applyTransform(ol.proj.getTransform('EPSG:4326', 'EPSG:3857'))
,(部分圖形展現請看demo)var polygon = new ol.geom.Polygon([[[110, 39], [116, 39], [116, 33], [110, 33], [110, 39]]]); polygon.applyTransform(ol.proj.getTransform('EPSG:4326', 'EPSG:3857')); // 座標轉換 var square = new ol.Feature({ geometry:polygon }) layer.getSource().addFeature(square)
一個style對象,包含Style類,有7個屬性:
// 最簡單的呈現方式,複雜的請參考demo var layer = new ol.layer.Vector({ source: new ol.source.Vector({ features:[new ol.Feature({ geometry: new ol.geom.Point(ol.proj.transform([104, 30], 'EPSG:4326', 'EPSG:3857')), })] }), style: new ol.style.Style({ image: new ol.style.Circle({ radius: 30, fill: new ol.style.Fill({ color: 'red' }) }) }), opacity:0.5 }) map.addLayer(layer)
一個層layer有一個featrue,也能夠有多個feature,由於Feature類是Vector類用來在地圖上展現幾何對象,是Vector圖層類一個屬性。這個屬性是個*要素數組*。
對於style樣式問題,feature的style的層級比layer.Vector的層級要高,因此feature的style會覆蓋layer的style。
ps:feature中的樣式不能以屬性名的形式寫,由於feature類中沒有style屬性名,只有geometry
,因此要以方法的形式去添加,setStyle()。
其實關於layer,vector,API上都有其方法,包括set/get,雖然類有不少子類,子類又有不少子子類,也無妨,只要抓住想要操做的是哪個部分就行,是feature,仍是layer,仍是geometry等等。
styleFunction
在feature
中可使用styleFunction
來設置本身爲所欲爲的樣式,經過官網API文檔能夠看到,其類型爲ol.FeatureStyleFunction,函數僅帶有一個參數resolution,在函數體內this指的是當前的feature,根據文檔說明,這個函數要返回一個style數組。
除了feature能夠設置樣式以外,layer也是能夠設置樣式的,一樣地也支持styleFunction,可是須要注意的是,其定義和feature的不同,類型爲ol.style.StyleFunction,該函數具備兩個參數,第一個參數爲feature,第二個參數爲resolution,一樣地,該函數須要返回style數組。
var layer = new ol.layer.Vector({ source: new ol.source.Vector() }) var map = new ol.Map({ layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }), layer ], target: 'map', view: new ol.View({ projection: 'EPSG:4326', center: [104, 30], zoom: 10 }) }); var anchor = new ol.Feature({ geometry: new ol.geom.Point([104, 30]) }); // 應用style function,動態的獲取樣式 anchor.setStyle(function(resolution){ return [new ol.style.Style({ image: new ol.style.Icon({ src: '../img/anchor.png', scale: map.getView().getZoom() / 10 }) })]; }); layer.getSource().addFeature(anchor);
地圖控件,包括縮放按鈕,標尺,版權說明,指北針等等,不會隨着地圖的放大而放大,縮小而縮小,就至關於position:fixed同樣,固定在某個地方。 在實現上,並非在畫布上繪製的,而是使用傳統的HTML元素來實現的,便於同地圖分離,也便於界面實現。
在openlayers 3 中,默認狀況下,在地圖上是不會顯示這麼多地圖控件的,只會應用ol.control.defaults()這個函數返回的地圖控件,默認包含了ol.control.Zoom,ol.control.Rotate和ol.control.Attribution這個控件。
OpenLayers 3目前內置的地圖控件類都在包ol.control下面:
var map = new ol.Map({ target:'map', layers:[new ol.layers.Tile({ source: new ol.source.OSM() })], view: new ol.View({ center:[0,0], projection: 'EPSG:4326', zoom:10, }) controls: ol.control.defaults({ attribution: false, // 信息false rotate: false, // 旋轉false zoom: false // 縮放false }) })
map.getControls()是獲取控件的信息,
若是想要添加其餘的控件,可使用map中的一個方法,map.addControl()
map.addControl(ol.control.OverviewMap) // 添加鳥瞰圖控件
控件不是在畫布上繪製的,而是用html實現的,因此樣式問題能夠按照css+html的形式去修改。
交互,就是人與機之間的交互模式,好比用鼠標左鍵雙擊地圖能夠放大地圖,按住鼠標左鍵拖動地圖能夠移動瀏覽地圖,用滾動鼠標中間的滑輪能夠放大縮小地圖等等。這些都是openLayers內置的,其實也能夠本身去interact。
內置的交互在map中都是默認的。
var map = new ol.Map({ interactions: ol.interaction.defaults().extends() // .... 其他代碼 })
ol.interaction.defaults()默認包含如下交互:
注意:須要設置tabindex,才能使div得到鍵盤事件
,就是在聲明id的那個div中添加:tabindex="0")
若是想要取消某個交互事件
var map = new ol.Map({ interactions: ol.interaction.defaults({ mouseWheelZoom: false, // 取消滾動鼠標中間的滑輪交互 shiftDragZoom: false, // 取消shift+wheel左鍵拖動交互 }) // .... 其他代碼 })
extend()爲擴展
var map = new ol.Map({ interactions: ol.interaction.defaults().extend() // .... 其他代碼 })
map.getInteraction()是獲取控件的信息,
若是想要添加其餘的交互,可使用map中的一個方法,map.addInteraction()
map.addInteraction(new ol.interaction.MouseWheelZoom);
關於new Interaction(),總共有7個子類,能夠用在extend([])中,也能夠用addInteraction()
Draw
interaction,繪製地理要素功能;Select
interaction,選擇要素功能;Modify
interaction,更改要素;這些子類均可以查API,有詳細解釋。這些子類中,有個經常使用的屬性condition
或方法handleEvent(mapBrowserEvent)
condition
表明的是事件名稱,好比:click,doubleClick,主要是依據ol.events
。主要有如下幾種,默認是singleClick
handleEvent(mapBrowserEvent)
function (mapBrowserEvent){ return ol.events.condition.click(mapBrowserEvent) && ol.events.condition.shiftKeyOnly(mapBrowserEvent); }
是個選擇圖形的類,用於交互.
new ol.interaction.Select(options)
options是個對象參數,包括:
selectSingleClick.on('select', function (event) { console.log(event) })
該select也有set/get方法,用來獲取或者設置屬性,好比獲取選中的features,獲取全部屬性名稱和值的對象getProperties。
是個繪製圖形的類,默認支持繪製的圖形類型包含 Point(點)、LineString(線)、Polygon(面)和Circle(圓)。觸發的事件包含 drawstart和drawend,分別在勾繪開始時候(單擊鼠標)和結束時候觸發(雙擊鼠標)。
new ol.interaction.Draw(options)
options是個對象參數,包括:
Point
LineString
Polygon
Circle
var drawLayer = new ol.layer.Vector({ source:new ol.source.Vector() }) // 新建一個層 map.addLayer(drawLayer) var draw = new ol.interaction.Draw({ source: drawLayer.getSource(), // 數據源就是新建層的數據源 type: 'Point', }) map.addInteraction(draw);
var draw = new ol.interaction.Draw({ // 繪製矩形 type: 'LineString', maxPoints: 2, geometryFunction: function(coordinates, geometry){ if(!geometry){ geometry = new ol.geom.Polygon(null); } var start = coordinates[0]; var end = coordinates[1]; geometry.setCoordinates([ [start, [start[0], end[1]], end, [end[0], start[1]], start] ]); return geometry; } // 其他代碼塊 })
// 繪製結束時進行回調 draw.addEventListener('drawend', function (evt) { // 獲取繪製圖形的全部座標點(終止點是起始點) var feature = evt.feature var geometry = feature.getGeometry() var coordinate = geometry.getCoordinates() // console.log(coordinate) var lent = coordinate[0].length // 座標點個數 })
用於修改要素幾何的交互。要修改已添加到現有源的功能,請使用該source選項構建修改交互,若是要修改集合中的要素(例如,選擇交互使用的集合),請使用該features選項構建交互。必須使用source或features構建交互
默認狀況下,交互將容許在alt 按下鍵時刪除頂點。要配置具備不一樣刪除條件的交互,請使用該deleteCondition選項。
new ol.interaction.Modify(options)
options是一個參數對象,以下:
在修改或繪製矢量要素時處理矢量要素的捕捉。這些功能能夠來自一個module:ol/source/Vector或module:ol/Collection-Collection 任何交互對象,容許用戶使用鼠標與功能進行交互能夠從捕捉中受益,只要它以前添加。
快照交互會修改地圖瀏覽器事件coordinate和pixel 屬性,以強制對其進行的任何交互進行快照。
new ol.interaction.Snap(options)
看API
options:
官方例子Snap Interaction
var map = new ol.Map({ layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], target: 'map', view: new ol.View({ center: ol.proj.transform( [104, 30], 'EPSG:4326', 'EPSG:3857'), zoom: 10 }) }); // 監聽singleclick事件 map.on('singleclick', function(event){ // 經過getEventCoordinate方法獲取地理位置,再轉換爲wgs84座標,並彈出對話框顯示 alert(ol.proj.transform(map.getEventCoordinate(event), 'EPSG:3857', 'EPSG:4326')); })
任意的事件應用,必然會有三個步驟:
編寫事件響應函數,在OpenLayers中,事件發送者都會有一個名字爲on的函數,調用這個函數,就能監聽指定的事件,響應函數listener具備一個參數event,這個event類就對應於API文檔中事件名稱後邊括號裏的類。
forEachFeatureAtPixel(pixel, callback, opt_options)
// 建立事件監聽器 var singleclickListener = function(event){ alert('...'); // 在響應一次後,註銷掉該監聽器 map.un('singleclick', singleclickListener); }; map.on('singleclick', singleclickListener);
// 使用once函數,只會響應一次事件,以後自動註銷事件監聽 map.once('singleclick', function(event){ alert('...'); })
要添加自定義事件,須要知道這樣一個事實:ol.Feature繼承於ol.Object,而ol.Object具備派發事件(dispatchEvent)和監聽事件(on)的功能。
on(type, listener) 觸發type類型的監聽器。
// 爲地圖註冊鼠標移動事件的監聽 map.on('pointermove', function (event) { map.forEachFeatureAtPixel(event.pixel, function (feature) { // 爲移動到的feature發送自定義的mousemove消息 feature.dispatchEvent({ type: 'mousemove', event: event }); // feature.dispatchEvent('mousemove'); }); }); // 爲feature1(以前建立的一個feature)註冊自定義事件mousemove的監聽 feature1.on('mousemove', function (event) { // 修改feature的樣式爲半徑100像素的園,用藍色填充 this.setStyle(new ol.style.Style({ image: new ol.style.Circle({ radius: 100, fill: new ol.style.Fill({ color: 'blue' }) }) })); });
dispatchEvent的參數具備type和event屬性,必須這樣構造嗎?在回答這個問題以前,須要先看一下API文檔,發現參數類型爲goog.events.EventLike,說明它其實用的是google的closure庫來實現的,經過closure庫的源碼咱們知道,派發的事件若是是一個對象,那麼必須包含type屬性,用於表示事件類型。其餘的屬性能夠自由定義,好比此處定義了event屬性,並設置對應的值,爲的是讓鼠標事件傳遞給feature1的監聽函數。dispatchEvent的參數會被原封不動的傳遞給事件響應函數,對應代碼`feature1.on('mousemove', function(event){}`裏參數event,能夠經過調試窗口看到此處的event和dispatchEvent的參數是同樣的。注意事件名稱是能夠自定義的,只要派發和監聽使用的事件名稱是一致的就能夠。
除了能夠經過dispatchEvent({type: 'mousemove', event: event})這種形式派發一個事件以外,還能夠經過dispatchEvent('mousemove')這中形式直接發送mousemove事件。
openlayers功能不少,有的地方本身因時間有限尚未深刻了解,可是大部分是夠用了,有大部分都是參考資料的,由於講的很通透,因此就拿過來了。,對於openylayers3,必定多看看官方例子,例子有不少吸取的知識點,特別有用
。有時間後會本身補上這一環節,你們若是有疑問或者我不對的地方請下方評論或私信。你們一塊兒進步加油!