开源地图库OpenLayers的简单使用
引言
最近在學習可視化的東西,這讓我想起了一些以前用過的圖表庫,其實我在日常做的大多是普通的需求,可視化方面應用的并不多,只是偶爾會因為個別特殊的需求,去借助一些圖表庫來實現圖表的展示,這些普通的圖表庫,在使用上都大差不差,并沒有什么太大的區別,但是某些特殊的圖表庫,比如地圖庫,在使用上和一些普通的圖表,還是存在一些不同,現在想一想還是需要做一些記錄,因為我沒有在當時使用的時候及時記錄,導致我現在對OpenLayers的使用也有一點模糊了,只能借助代碼來回憶,所以我現在把它的簡單使用做一次整理。
其實一開始我選擇使用的是比較普遍的高德地圖,但是需求做到后面,我才意識到當時做的項目是要部署在內網的,當時就有點傻眼了,因為我對WebGIS也并不熟悉,所以就上網匆匆的搜索有什么容易上手使用的開源地圖庫,然后鎖定了OpenLayers這個庫。
OpenLayers使用起來不像高德地圖那么方便,因為部署的是內網環境,需要自己準備瓦片服務,還記得當時下載地圖瓦片也下載了很久,因為要準備不同比例的地圖瓦片,不過幸好當時只需要下載杭州一個城市的瓦片。
準備工作
雖然之前我是在React的項目中使用OpenLayers的,但OpenLayers的使用與項目的具體框架并沒有太大的關系,所以我們只需要使用script標簽引入OpenLayers,就可以在項目中使用這個開源地圖庫了。
因此我們的準備工作,只需要一個引入OpenLayers的頁面,然后在頁面上準備一個div,來作為地圖的容器就可以了,另外在這個例子中我使用了systemjs來進行瀏覽器端的包管理,不用也是可以的;當然,地圖瓦片也是需要提前準備的。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>OpenLayers demo</title>
<script type="systemjs-importmap">
{
"imports": {
"ol": "https://cdn.jsdelivr.net/npm/ol@v8.2.0/dist/ol.js"
}
}
</script>
<link rel="stylesheet" >
<script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/system.js"></script>
<script src="https://cdn.jsdelivr.net/npm/systemjs@6.8.3/dist/extras/use-default.js"></script>
</head>
<body>
<div id="map" style="width: 500px; height: 500px;"></div>
</body>
</html>
地圖瓦片
地圖瓦片是什么呢?簡單來說,它是地圖視圖的組成單元,也就是說,地圖的視圖是由一張張的瓦片拼湊而成。但是地圖的使用一般而言不是靜態的,通常在使用中我們需要對地圖進行縮放交互,來進行更細致的觀察。所以我們一般需要準備多個比例下的地圖瓦片,具體的可以根據需求來確定。
雖然當時我查到可以由后端部署服務來提供瓦片,但因為當時比較匆忙,我沒來得及仔細研究,又覺得說本來這塊工作量之前也并不了解,前端這邊如果能直接處理就處理了,所以就用地圖瓦片下載器自己去下載了瓦片,然后部署到一個靜態服務下面;現在對于demo的編寫倒也是一個好處,可以方便前端的獨立展示。
實現效果
因為是簡單的使用,所以這里我們主要實現地圖的展示、放大縮小等簡單的功能,以及一些簡單的交互處理。
具體實現
總體來說,Openlayers的使用并不復雜,普通的使用通過查閱API文檔完全可以應對。
-
首先我們提前把下載好的地圖瓦片放到服務目錄下。
-
然后是最基本的,使用
System.import方法引入ol依賴const ol = await System.import('ol'); -
然后我們關注三個主要的類,分別是Map、View和TileLayer,這是我們用于構筑地圖的主要部分
const OlMap = ol.Map, View = ol.View, TileLayer = ol.layer.Tile; -
現在我們就可以通過new Map來創建新的地圖對象
const map = new OlMap({ target: 'map', view: new View({ center: [120.212, 30.208], projection: 'EPSG:4326', zoom: 9, maxZoom: 17, minZoom: 7 }), });其中target用于指定盛裝地圖的容器;
在創建地圖對象的時候,會使用到View這個類,代表地圖的二維視圖。我們可以在視圖中通過經緯度數組指定視圖的中心,View默認使用EPSG3857坐標系設置,我們也可以通過projection選項來修改坐標系,之前我使用的時候比較匆忙,沒有注意到這一塊,還很曲折的通過
fromEPSG4326方法來把4326的經緯度轉換為3857坐標系;zoom選項用于定義視圖初始分辨率的縮放級別,這里我當時是用了9這個級別,我感覺比較合適,當然具體的設置要看項目需求;然后我們可以通過maxZoom和minZoom這兩個選項限制最大和最小的縮放級別。現在我們就可以看到,頁面上其實已經生成地圖容器了,已經能看到放大縮小的操作按鈕了,只是說還沒有貼上瓦片,所以這時候的地圖還比較抽象。
-
接下來我們就需要用到之前準備的瓦片了,用于給map對象設置layers圖層
layers選項接收的是一個數組,也就是說可以給地圖配置多個圖層;這里我們使用剛剛引入的TileLayer這個類來創建一個圖層;另外我們還需要使用一個XYZ的類,來指定瓦片服務的地址。// ... const XYZ = ol.source.XYZ; const map = new OlMap({ target: 'map', view: new View({ center: [120.212, 30.208], projection: 'EPSG:4326', zoom: 9, maxZoom: 17, minZoom: 7 }), layers: [ new TileLayer({ source: new XYZ({ url: './maps/{z}/{x}/{y}.png' }) }) ] });
至此我們就可以在頁面上看到地圖的展示了,打開控制臺我們也可以看到對地圖瓦片的請求,請求的是maps/9目錄下的瓦片,我們也能注意到,有一些404的請求,這是因為view圖層中的部分地圖瓦片我們沒有準備,通過在頁面上檢查元素,也可以看到map容器中確實存在一部分沒有貼上瓦片,這通常來說沒什么關系,可以不用管;可以看到當使用鼠標滾動縮放地圖的時候,也會去請求相應縮放比例的地圖瓦片。
-
添加簡單的交互事件
最后來添加一些簡單的交互。
之前我做的需求中需要根據接口返回的數據批量標注地圖上的點,但是因為現在沒有數據,這里就實現一些簡單的交互吧。const olExtent = ol.extent; map.on('moveend', e => { console.log('zoom', map.frameState_.viewState.zoom); const extent = map.frameState_.extent; console.log('extent', extent); console.log('TopLeft', olExtent.getTopLeft(extent)); console.log('BottomRight', olExtent.getBottomRight(extent)); });我們可以通過zoom獲取視圖的縮放級別,通過extent獲取視圖的經緯度范圍,還可以進一步通過extent的getTopLeft和getBottomRight分別獲取左上角的經緯度和右下角的經緯度;這樣我們就可以在縮放視圖和移動圖層時根據視圖的經緯度范圍來加載相應的數據。
const Feature = ol.Feature; const Point = ol.geom.Point; const Style = ol.style.Style, CircleStyle = ol.style.Circle, Fill = ol.style.Fill, Stroke = ol.style.Stroke; const VectorSource = ol.source.Vector, VectorLayer = ol.layer.Vector; let count = 0; map.on('click', e => { const features = []; console.log(e.coordinate); // 獲取坐標 const iconFeature = new Feature({ geometry: new Point(e.coordinate), name: count ++, location: e.coordinate }); const style = new Style({ image: new CircleStyle({ radius: 10, fill: new Fill({ color: '#f49d41' }), stroke: new Stroke({ color: '#836365', width: 1 }) }) }); iconFeature.setStyle(style); features.push(iconFeature); const vectorSource = new VectorSource({ features }); const vectorLayer = new VectorLayer({ source: vectorSource, opacity: 0.8 }); map.addLayer(vectorLayer); });我們還可以在處理地圖的鼠標點擊事件時,獲取鼠標點對應的經緯度,通過Feature類給地圖添加標注,再通過Style類給標注設置樣式;也可以在添加新標注前移除舊的標注。
const layers = map.getLayers(); layers.forEach(item => { if(item instanceof VectorLayer) map.removeLayer(item); });
到這里我們就完成了OpenLayers的簡單使用,如果有感興趣的小伙伴,可以去OpenLayers的GitHub和官方文檔再去進一步的了解。
以下是運行效果:
整體代碼參考這個CodePen
總結
以上是生活随笔為你收集整理的开源地图库OpenLayers的简单使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 华硕 ROG 冰刃 X 电竞主机预售:1
- 下一篇: 99 元,小米无线鼠标静音版 E318