openlayers 知識 前段時間幫助同事重構一個地圖類的項目,然後就學習了openLayer3這個框架,但是官網上沒有中文版,也沒有詳細的例子解釋,我只能遇到看不懂的就翻譯成中文來用,為了方便以後再用這個ol,能夠更快的上手,就花了幾天的時間總結了ol的知識,ol功能很豐富,API也很多,沒有寫 ...
openlayers 知識
前段時間幫助同事重構一個地圖類的項目,然後就學習了openLayer3這個框架,但是官網上沒有中文版,也沒有詳細的例子解釋,我只能遇到看不懂的就翻譯成中文來用,為了方便以後再用這個ol,能夠更快的上手,就花了幾天的時間總結了ol的知識,ol功能很豐富,API也很多,沒有寫太多,只是寫了怎麼用的,只要學會了根本,就可以很快的使用API去操作map。
另外,在總結知識的同時,還寫了demo,加深自己的理解,大家覺得不錯的話,給個star~ GitHub
那麼開始吧!
目錄
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 --> 控制項,類似與按鈕,有放大,縮小,全屏等的按鈕
最簡單的顯示地圖:
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,map = new ol.Map()
;在openlayers3 的API中,有很多方法,可以通過方法去操作layers,view,interactions,controls。
列印map,可以發現map裡面有很多屬性,可以簡單知道map上有多少個層,target是誰,size是多少等等,也可以通過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
視圖
.View對象表示地圖的簡單2D視圖。這是用於更改地圖的中心,解析度和旋轉的對象。
一個視圖是由三種狀態確定:center,resolution,zoom和rotation。每個狀態具有相應的獲取和設置。
- center:初始坐標,比如:成都的位置 [104.06, 30.67],這樣地圖初始化會以成都為中心展開(projection:'EPSG:4326')。
- projection:一個視圖有一個projection。投影確定中心的坐標系,其單位確定解析度的單位(每像素的投影單位)。
projection有兩種值,預設投影是球形墨卡托(EPSG:3857),是地圖的xy坐標,另一種就是經緯度坐標,(EPSG:4326)是WGS84的一種。
通過一個方法可以進行EPSG:3857與EPSG:4326轉化。
經緯度轉至xy(EPSG:4326->EPSG:3857)
ol.proj.transform(coordinates,'EPSG:4326','EPSG:3857')
xy轉至經緯度(EPSG:3857->EPSG:4326)
ol.proj.transform(coordinates,'EPSF:3857','EPSG:4326')
- zoom:計算視圖初始解析度的縮放級別。至於resolution初始解析度,在其未聲明時,zoom起作用。對應的它也有maxZoom,minZoom。
- rotation:初始旋轉度,預設是0,(順時針正向旋轉,0表示北向),弧度制
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) // 獲取此視圖的約束旋轉
layers
層,是一個對象數組,將那些與數據顯示方式相關的屬性組合在一起,形成一個層,openlayer就是由一個一個的層形成的,包括地圖,瓦片地圖,圖片,圖形都是由layer形成而呈現在map上的
簡單的來說,layer可以是一個地圖,也可以是一個圖形,也可以是個圖片,因為是個數組,可以互相疊加的,[map,image,shape],在相同位置的情況下,後者會覆蓋前者。
根據這個圖片可知,layers有三種形式
- ol.layer.Tile 瓦片,瓦片地圖源於一種大地圖解決方案,針對一整塊非常大的地圖進行切片,分成很多相同大小的小塊地圖,在用戶訪問的時候,再一塊一塊小地圖載入,拼接在一起,從而還原成一整塊大的地圖。這樣做的優點在於,用戶在同一時間,同一個可見視圖內,只能看到地圖的一部分,而不是全部。提高用戶體驗。通常用這個作為底圖。
- ol.layer.Image 對應的是一整張圖,而不像瓦片那樣很多張圖,從而無需切片,也可以載入一些地圖,適用於一些小場景地圖
- ol.layer.Vector 矢量,使用直線和曲線來描述圖形,這些圖形的元素是一些點、線、矩形、多邊形、圓和弧線等等,它們都是通過數學公式計算獲得的。由於矢量圖形可通過公式計算獲得,所以矢量圖形文件體積一般較小。矢量圖形最大的優點是無論放大、縮小或旋轉等不會失真。
每個形式都需要一個source,數據源,所以每一個形式都對應一個數據源,Source和Layer是一對一的關係,有一個Source,必然需要一個Layer,然後把這個Layer添加到Map上,就可以顯示出來了。
ol.layer.Tile
對於瓦片數據源,也有很多屬性,
- opacity,改變透明度,預設是1
- visible,可視,預設是true
- zIndex,圖層渲染的z-index。在渲染時,將按照Z-index然後按位置對圖層進行排序
source
有很多形式,- 線上服務的Source
- ol.source.OSM
- ol.source.BingMaps
- ol.source.TileImage
- 支持協議標準的Source,包括ol.source.TileArcGISRest,ol.source.TileWMS,ol.source.WMTS,ol.source.UTFGrid,ol.source.TileJSON。如果要使用它們,首先你得先學習對應的協議,之後必須找到支持這些協議的伺服器來提供數據源,這些伺服器可以是地圖服務提供商提供的,也可以是自己搭建的伺服器,關鍵是得支持這些協議。
- ol.source.XYZ,而且現在很多地圖服務(線上的,或者自己搭建的伺服器)都支持xyz方式的請求。國內線上的地圖服務,高德,天地圖等,都可以通過這種方式載入的
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.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);
ol.layer.Vector
矢量圖層,是用來渲染矢量數據的圖層類型,在OpenLayers里,它是可以定製的,可以控制它的透明度,顏色,以及載入在上面的要素形狀等。常用於從資料庫中請求數據,接受數據,並將接收的數據解析成圖層上的信息。比如將滑鼠移動到中國,相應的區域會以紅色高亮顯示出來,高亮便是矢量圖層的行為
既然是個矢量圖,可以改變大小,顏色,以及形狀。包含source數據源類,style類設置樣式,以及其他的zIndex,opacity等等。
Feature類是Vector類用來在地圖上展示幾何對象,是Vector圖層類一個屬性。這個屬性是個*要素數組*。
source
對應的數據源ol.source.Vector也是個對象。最常見屬性的是features
和format
以及url
。通常url和format一塊,url按理傳來的是geojson格式的矢量圖,需要format格式化一下。最常用還是features。
ol.Feature
- feature 具有幾何和其他屬性屬性的地理要素的矢量對象,類似於GeoJSON等矢量文件格式中的要素。
- Geometry類是feature對象的基本組成部分,Vector類採用Geometry類來存儲一個要素的幾何信息.通過
feature名.getGeometry()
獲取 - feature類有兩個部分,Geometry對象和attributes屬性,attributes包含要素相關的數據。比如:{type:'circle'},通過getProperties().attributes去獲取。
geometry - new ol.geom.Point([x1,y1]) 點
- new ol.geom.LineString([[x1,y1],[x2,y2]]) 線
- new ol.geom.LinearRing()
- new ol.geom.MultiLineString([[[x1,y1],[x2,y2]],[[x3,y3],[x4,y4]],[...]]) 多條線
- new ol.geom.MultiPoint([[x1,y1],[x2,y2],[...]]) 多個點
- new ol.geom.Polygon([[[x1,y1],[x2,y2],[x3,y3],[x4,y4],[...],[x1,y1]]]) 幾何
如果這些坐標是經緯度坐標的話,都需要坐標轉換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對象,包含Style類,有7個屬性:
- geometry 返回要為此樣式渲染的幾何的要素屬性或幾何或函數
- fill 填充樣式。
- image 圖像樣式
- icon : new ol.style.Icon()
- anchor :[0.5,0.5]錨點,
- color
- src :圖標源
- ...
- circle: new ol.style.Circle()
- fill :new ol.style.Fill()
- radius : 半徑
- stroke :new ol.style.Stroke()
- regularShape :new ol.style.RegularShape()
- fill :new ol.style.Fill()
- points : 點數,幾個點
- radius : 半徑
- radius1 : 外半徑
- radius2 : 內半徑
- angle 0 形狀的角度以弧度表示。值為0將使其中一個形狀的點朝上。
- stroke :new ol.style.Stroke()
- rotation : 0 旋轉度
- ...
- icon : new ol.style.Icon()
- renderer 自定義渲染器。配置時fill,stroke和image將被忽略,並且將為每個幾何體的每個渲染幀調用提供的函數。
- stroke 邊線樣式
- color 顏色
- lineCap :butt, round, square 線帽
- lineJoin :bevel, round, miter. 線條連接形狀
- width 寬度
- text 文字樣式
- font :'10px sans-serif'
- text
- textAlign left','right','center','end' start'
- fill :new ol.style.Fill()
- stroke :new ol.style.Stroke()
- backgroundFill
- padding
- zIndex 層級
// set*()在重新呈現使用該樣式的要素或圖層之前,通過方法對樣式或其子項所做的任何更改都不會生效
// 最簡單的呈現方式,複雜的請參考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);
controls
地圖控制項,包括縮放按鈕,標尺,版權說明,指北針等等,不會隨著地圖的放大而放大,縮小而縮小,就相當於position:fixed一樣,固定在某個地方。 在實現上,並不是在畫布上繪製的,而是使用傳統的HTML元素來實現的,便於同地圖分離,也便於界面實現。
在openlayers 3 中,預設情況下,在地圖上是不會顯示這麼多地圖控制項的,只會應用ol.control.defaults()這個函數返回的地圖控制項,預設包含了ol.control.Zoom,ol.control.Rotate和ol.control.Attribution這個控制項。
OpenLayers 3目前內置的地圖控制項類都在包ol.control下麵:
- ol.control.Attribution: 右下角的地圖信息控制項
- ol.control.FullScreen: 全屏控制項
- ol.control.MousePosition: 滑鼠位置控制項
- ol.control.OverviewMap: 鳥瞰圖控制項
- ol.control.Rotate: 指北針控制項
- ol.control.ScaleLine: 比例尺控制項
- ol.control.Zoom: 縮放按鈕控制項
- ol.control.ZoomSlider: 縮放滾動條控制項
- ol.control.ZoomToExtent: 放大到設定區域控制項
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的形式去修改。
interactions
交互,就是人與機之間的交互模式,比如用滑鼠左鍵雙擊地圖可以放大地圖,按住滑鼠左鍵拖動地圖可以移動瀏覽地圖,用滾動滑鼠中間的滑輪可以放大縮小地圖等等。這些都是openLayers內置的,其實也可以自己去interact。
內置的交互
內置的交互在map中都是預設的。
var map = new ol.Map({
interactions: ol.interaction.defaults().extends()
// .... 其餘代碼
})
ol.interaction.defaults()預設包含以下交互:
- 滑鼠
- 按住alt+shift鍵,用滑鼠左鍵拖動地圖,就能讓地圖旋轉,對應的交互類為ol.interaction.DragRotate。
- 用滑鼠左鍵雙擊地圖,就可以放大地圖,對應的交互類為ol.interaction.DoubleClickZoom。
- 用滑鼠左鍵,拖拽地圖,就可以平移地圖,對應的交互類為ol.interaction.DragPan。
- 滾動滑鼠中間的滑輪,就可以縮放地圖,對應的交互類為ol.interaction.MouseWheelZoom。
- 按住shift鍵,同時用滑鼠左鍵在地圖上拖動,就可以放大地圖,對應的交互類為ol.interaction.DragZoom。
- 觸摸屏
- 在觸摸屏上,用兩個手指在觸摸屏上旋轉,就可以旋轉地圖,對應的交互類為ol.interaction.PinchRotate。
- 在觸摸屏上,用兩個手指在觸摸屏上縮放,就可以縮放地圖,對應的交互類為ol.interaction.PinchZoom。
- 鍵盤(
註意:需要設置tabindex,才能使div獲得鍵盤事件
,就是在聲明id的那個div中添加:tabindex="0")- 用鍵盤上的上下左右鍵,就可以平移地圖,對應的交互類為ol.interaction.KeyboardPan。
- 用鍵盤上的+/-鍵,就可以縮放地圖,對應的交互類為ol.interaction.KeyboardZoom。
如果想要取消某個交互事件
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()
- DoubleClickZoom interaction,雙擊放大交互功能;
- DragAndDrop interaction,以“拖文件到地圖中”的交互添加圖層;
- DragBox interaction,拉框,用於劃定一個矩形範圍,例子常用於放大地圖;
- DragPan interaction,拖拽平移地圖;
- DragRotateAndZoom interaction,拖拽方式進行縮放和旋轉地圖;
- DragRotate interaction,拖拽方式旋轉地圖;
- DragZoom interaction,拖拽方式縮放地圖;
Draw
interaction,繪製地理要素功能;- KeyboardPan interaction,鍵盤方式平移地圖;
- KeyboardZoom interaction,鍵盤方式縮放地圖;
Select
interaction,選擇要素功能;Modify
interaction,更改要素;- MouseWheelZoom interaction,滑鼠滾輪縮放功能;
- PinchRotate interaction,手指旋轉地圖,針對觸摸屏;
- PinchRoom interaction,手指進行縮放,針對觸摸屏;
- Pointer interaction,滑鼠的用戶自定義事件基類;
- Snap interaction,滑鼠捕捉,當滑鼠距離某個要素一定距離之內,自動吸附到要素。
這些子類都可以查API,有詳細解釋。這些子類中,有個常用的屬性condition
或方法handleEvent(mapBrowserEvent)
condition
代表的是事件名稱,比如:click,doubleClick,主要是依據ol.events
。主要有以下幾種,預設是singleClick
- altKeyOnly 僅按下alt鍵則返回true
- shiftKeyOnly 僅按下shift鍵則返回true
- altShiftKeysOnly 僅按下alt鍵+shift則返回true
- always
- never
- click,只要是點擊,包括singleClick,doubleClick都返回true
- doubleClick
- singleClick
- focus 如果地圖具有焦點,則返回true。此條件需要具有tabindex屬性的地圖目標元素,例如。
- mouseOnly 從滑鼠設備發起為true
- noModifierKeys 沒有組合鍵則返回true
- pointerMove 指針移動時返回true
- targetNotEditable 如果目標元素不可編輯,則返回true,即不是input,select或textarea元素false。
- platformModifierKeyOnly
- primaryAction 從一個主指針在與錶面接觸或起源如果按下滑鼠左鍵
handleEvent(mapBrowserEvent)
function (mapBrowserEvent){
return ol.events.condition.click(mapBrowserEvent) && ol.events.condition.shiftKeyOnly(mapBrowserEvent);
}
Select
是個選擇圖形的類,用於交互.
new ol.interaction.Select(options)
options是個對象參數,包括:
- style
- layers 應從中選擇要素的圖層列表。或者,可以提供過濾功能。將為地圖中的每個圖層調用該函數,並應返回true您想要選擇的圖層。如果該選項不存在,則所有可見圖層都將被視為可選擇。
- condition 類型為 ol.events.ConditionType,規定了什麼情況下觸發 select 操作,預設不需要特殊條件進行觸發。
- addCondition
- removeCondition
- toggleCondition 獲取module:ol/MapBrowserEvent-MapBrowserEvent和返回布爾值的函數,以指示是否應該處理該事件。這是condition事件的補充。預設情況下, module:ol/events/condition-shiftKeyOnly即按下shift以及condition事件,如果當前未選中,則將該功能添加到當前選擇,如果是,則將其刪除。見add而remove 如果你想使用的,而不是一個觸發不同的事件。
- multi 用於確定預設行為是否應僅在單擊的地圖位置選擇單個feature或所有(重疊)feature。預設值false表示單選。
- features
- filter 過濾 見demo
- wrapX 當地圖水平顯示多個相同位置時,是否顯示多個勾繪任務,預設為 false
select點擊事件
selectSingleClick.on('select', function (event) {
console.log(event)
})
該select也有set/get方法,用來獲取或者設置屬性,比如獲取選中的features,獲取所有屬性名稱和值的對象getProperties。
Draw
是個繪製圖形的類,預設支持繪製的圖形類型包含 Point(點)、LineString(線)、Polygon(面)和Circle(圓)。觸發的事件包含 drawstart和drawend,分別在勾繪開始時候(單擊滑鼠)和結束時候觸發(雙擊滑鼠)。
new ol.interaction.Draw(options)
options是個對象參數,包括:
- type: 幾何類型(加粗為預設)
Point
LineString
- LinearRing
Polygon
- MultiPoint
- MultiLineString
- MultiPolygon
- GeometryCollection
Circle
- source 數據源,如果想要保存繪製的圖形,需要有一個載體來存儲繪製的圖形,比如新建一個layer,這個layer的source就是該繪製的source。
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);
- style
- stopClick
- condition 類型為 ol.events.ConditionType,規定了什麼情況下觸發 draw 操作,預設不需要特殊條件進行觸發。
- clickTolerance: 數值類型,單位是像素,判斷用戶滑鼠(PC)或者手指(移動設備)的行為是添加點,還是按住滑鼠或者手指不鬆開進行拖拽地圖,預設值是 6 像素,也就是說當按下滑鼠和抬起滑鼠左鍵之間的這段時間段內,如果地圖被拖動沒有超過 6 像素,那麼預設為添加一個點,相反如果超過了 6 像素,那麼不會添加點,只是平移一下地圖。
- snapTolerance 數值,像素為單位,預設值是 12 像素,當一定位置內最後一個點吸附到第一個點,對多邊形時有用
- features
- maxPoints 表示繪製單個要素(面和線)最多的點數限制,預設沒有限制
- minPoints 表示繪製單個要素(面和線)需要的最少點數,面預設為 3,線預設為 2
- geometryName 字元串類型,繪製的 geometry 的名稱。
- geometryFunction 因為預設type只有四種:Point(點)、LineString(線)、Polygon(面)和Circle(圓),此方法就是可以用來繪製規則或者自己想要繪製的圖形的方法,該函數有兩個參數,一個是坐標集合、一個是勾繪的 geometry 類型,返回構造好的 geometry 對象,用來初始化要素。
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; } // 其餘代碼塊 })
- 上面的例子用LineString的形式去繪製矩形,這裡的原理就是捕捉滑鼠點擊的點,然後獲取限制的兩個點的坐標,用來初始化一個矩形框。
- wrapX 當地圖水平顯示多個相同位置時,是否顯示多個勾繪任務,預設為 false
- freehand 預設是false,是否以曲線的形式,不是規範化的,看demo-freehandDraw.html
- freehandCondition 類型同condition,也是 ol.events.ConditionType,這個選項規定了什麼情況下觸發不用重覆點擊繪製模式,即拖拽滑鼠就可以繪製圖形的模式,預設情況下是按下 shift 按鍵,這種模式對於不容易繪製的曲線比較方便,而且釋放 shift 情況下,如果沒有完成繪製,可以繼續使用點擊繪製。(就是需要輔助鍵,例如shift,ctrl時,會以曲線形式繪畫)--demo-secondDraw.html,按shift繪畫可以發現。
drawstart/drawend
// 繪製結束時進行回調
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 // 坐標點個數
})
Modify
用於修改要素幾何的交互。要修改已添加到現有源的功能,請使用該source選項構建修改交互,如果要修改集合中的要素(例如,選擇交互使用的集合),請使用該features選項構建交互。必須使用source或features構建交互
預設情況下,交互將允許在alt 按下鍵時刪除頂點。要配置具有不同刪除條件的交互,請使用該deleteCondition選項。
new ol.interaction.Modify(options)
options是一個參數對象,如下:
- condition
- style
- source
- features
- wrapX
- insertVertexCondition 一個函數,它接受module:ol/MapBrowserEventMapBrowserEvent並返回一個布爾值,以指示是否可以將新頂點添加到草圖要素中。預設是module:ol/events/condition-always。 同deletCondition
- deleteCondition 獲取module:ol/MapBrowserEventMapBrowserEvent和返回布爾值的函數,以指示是否應該處理該事件。預設情況下, module:ol/events/condition-singleClick與 module:ol/events/conditionaltKeyOnly在頂點缺失的結果。看demo-modifyDifficult.html(先選中後操作)
Snap
在修改或繪製矢量要素時處理矢量要素的捕捉。這些功能可以來自一個module:ol/source/Vector或module:ol/Collection-Collection 任何交互對象,允許用戶使用滑鼠與功能進行交互可以從捕捉中受益,只要它之前添加。
快照交互會修改地圖瀏覽器事件coordinate和pixel 屬性,以強制對其進行的任何交互進行快照。
new ol.interaction.Snap(options)
看API
options:
- features 應提供此選項或來源。
- edge 抓住邊緣。預設值時true
- vertex 捕捉到頂點。預設值是true
- source 捕捉此來源的功能。應提供此選項或功能
官方例子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'));
})
任意的事件應用,必然會有三個步驟:
- 找準事件發送者,比如上面這個例子,map就是事件發送者。 如何找到它呢? 一般都是要交互的對象。
- 找準事件名稱,比如上面例子中的singleclick,切忌不要隨便想象,或者按照慣例來寫名稱-condition,
編寫事件響應函數,在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)的功能。
- dispatchEvent(event) 分發一個事件,並調用偵聽此類事件的所有監聽器,event參數可以是字元串,也可以是具有type屬性的Object
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,一定多看看官方例子,例子有很多吸收的知識點,特別有用
。有時間後會自己補上這一環節,大家如果有疑問或者我不對的地方請下方評論或私信。大家一起進步加油!
參考資料
openlayer3
OpenLayers 3 Primer