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,一定多看看官方例子,例子有很多吸收的知識點,特別有用
。有時間後會自己補上這一環節,大家如果有疑問或者我不對的地方請下方評論或私信。大家一起進步加油!