日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

开源地图库OpenLayers的简单使用

發(fā)布時(shí)間:2023/12/24 windows 34 coder
生活随笔 收集整理的這篇文章主要介紹了 开源地图库OpenLayers的简单使用 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

引言

最近在學(xué)習(xí)可視化的東西,這讓我想起了一些以前用過(guò)的圖表庫(kù),其實(shí)我在日常做的大多是普通的需求,可視化方面應(yīng)用的并不多,只是偶爾會(huì)因?yàn)閭€(gè)別特殊的需求,去借助一些圖表庫(kù)來(lái)實(shí)現(xiàn)圖表的展示,這些普通的圖表庫(kù),在使用上都大差不差,并沒(méi)有什么太大的區(qū)別,但是某些特殊的圖表庫(kù),比如地圖庫(kù),在使用上和一些普通的圖表,還是存在一些不同,現(xiàn)在想一想還是需要做一些記錄,因?yàn)槲覜](méi)有在當(dāng)時(shí)使用的時(shí)候及時(shí)記錄,導(dǎo)致我現(xiàn)在對(duì)OpenLayers的使用也有一點(diǎn)模糊了,只能借助代碼來(lái)回憶,所以我現(xiàn)在把它的簡(jiǎn)單使用做一次整理。

其實(shí)一開始我選擇使用的是比較普遍的高德地圖,但是需求做到后面,我才意識(shí)到當(dāng)時(shí)做的項(xiàng)目是要部署在內(nèi)網(wǎng)的,當(dāng)時(shí)就有點(diǎn)傻眼了,因?yàn)槲覍?duì)WebGIS也并不熟悉,所以就上網(wǎng)匆匆的搜索有什么容易上手使用的開源地圖庫(kù),然后鎖定了OpenLayers這個(gè)庫(kù)。

OpenLayers使用起來(lái)不像高德地圖那么方便,因?yàn)椴渴鸬氖莾?nèi)網(wǎng)環(huán)境,需要自己準(zhǔn)備瓦片服務(wù),還記得當(dāng)時(shí)下載地圖瓦片也下載了很久,因?yàn)橐獪?zhǔn)備不同比例的地圖瓦片,不過(guò)幸好當(dāng)時(shí)只需要下載杭州一個(gè)城市的瓦片。

準(zhǔn)備工作

雖然之前我是在React的項(xiàng)目中使用OpenLayers的,但OpenLayers的使用與項(xiàng)目的具體框架并沒(méi)有太大的關(guān)系,所以我們只需要使用script標(biāo)簽引入OpenLayers,就可以在項(xiàng)目中使用這個(gè)開源地圖庫(kù)了。

因此我們的準(zhǔn)備工作,只需要一個(gè)引入OpenLayers的頁(yè)面,然后在頁(yè)面上準(zhǔn)備一個(gè)div,來(lái)作為地圖的容器就可以了,另外在這個(gè)例子中我使用了systemjs來(lái)進(jìn)行瀏覽器端的包管理,不用也是可以的;當(dāng)然,地圖瓦片也是需要提前準(zhǔn)備的。

<!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>

地圖瓦片

地圖瓦片是什么呢?簡(jiǎn)單來(lái)說(shuō),它是地圖視圖的組成單元,也就是說(shuō),地圖的視圖是由一張張的瓦片拼湊而成。但是地圖的使用一般而言不是靜態(tài)的,通常在使用中我們需要對(duì)地圖進(jìn)行縮放交互,來(lái)進(jìn)行更細(xì)致的觀察。所以我們一般需要準(zhǔn)備多個(gè)比例下的地圖瓦片,具體的可以根據(jù)需求來(lái)確定。

雖然當(dāng)時(shí)我查到可以由后端部署服務(wù)來(lái)提供瓦片,但因?yàn)楫?dāng)時(shí)比較匆忙,我沒(méi)來(lái)得及仔細(xì)研究,又覺(jué)得說(shuō)本來(lái)這塊工作量之前也并不了解,前端這邊如果能直接處理就處理了,所以就用地圖瓦片下載器自己去下載了瓦片,然后部署到一個(gè)靜態(tài)服務(wù)下面;現(xiàn)在對(duì)于demo的編寫倒也是一個(gè)好處,可以方便前端的獨(dú)立展示。

實(shí)現(xiàn)效果

因?yàn)槭呛?jiǎn)單的使用,所以這里我們主要實(shí)現(xiàn)地圖的展示、放大縮小等簡(jiǎn)單的功能,以及一些簡(jiǎn)單的交互處理。

具體實(shí)現(xiàn)

總體來(lái)說(shuō),Openlayers的使用并不復(fù)雜,普通的使用通過(guò)查閱API文檔完全可以應(yīng)對(duì)。

  • 首先我們提前把下載好的地圖瓦片放到服務(wù)目錄下。

  • 然后是最基本的,使用System.import方法引入ol依賴

    const ol = await System.import('ol');
    
  • 然后我們關(guān)注三個(gè)主要的類,分別是Map、View和TileLayer,這是我們用于構(gòu)筑地圖的主要部分

    const OlMap = ol.Map,
        	View = ol.View,
        	TileLayer = ol.layer.Tile;
    
  • 現(xiàn)在我們就可以通過(guò)new Map來(lái)創(chuàng)建新的地圖對(duì)象

    const map = new OlMap({
      target: 'map',
      view: new View({
        center: [120.212, 30.208],
        projection: 'EPSG:4326',
        zoom: 9,
        maxZoom: 17,
            minZoom: 7
      }),
    });
    

    其中target用于指定盛裝地圖的容器;

    在創(chuàng)建地圖對(duì)象的時(shí)候,會(huì)使用到View這個(gè)類,代表地圖的二維視圖。我們可以在視圖中通過(guò)經(jīng)緯度數(shù)組指定視圖的中心,View默認(rèn)使用EPSG3857坐標(biāo)系設(shè)置,我們也可以通過(guò)projection選項(xiàng)來(lái)修改坐標(biāo)系,之前我使用的時(shí)候比較匆忙,沒(méi)有注意到這一塊,還很曲折的通過(guò)fromEPSG4326方法來(lái)把4326的經(jīng)緯度轉(zhuǎn)換為3857坐標(biāo)系;zoom選項(xiàng)用于定義視圖初始分辨率的縮放級(jí)別,這里我當(dāng)時(shí)是用了9這個(gè)級(jí)別,我感覺(jué)比較合適,當(dāng)然具體的設(shè)置要看項(xiàng)目需求;然后我們可以通過(guò)maxZoom和minZoom這兩個(gè)選項(xiàng)限制最大和最小的縮放級(jí)別。

    現(xiàn)在我們就可以看到,頁(yè)面上其實(shí)已經(jīng)生成地圖容器了,已經(jīng)能看到放大縮小的操作按鈕了,只是說(shuō)還沒(méi)有貼上瓦片,所以這時(shí)候的地圖還比較抽象。

  • 接下來(lái)我們就需要用到之前準(zhǔn)備的瓦片了,用于給map對(duì)象設(shè)置layers圖層
    layers選項(xiàng)接收的是一個(gè)數(shù)組,也就是說(shuō)可以給地圖配置多個(gè)圖層;這里我們使用剛剛引入的TileLayer這個(gè)類來(lái)創(chuàng)建一個(gè)圖層;另外我們還需要使用一個(gè)XYZ的類,來(lái)指定瓦片服務(wù)的地址。

    // ...
    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'
          })
        })
      ]
    });
    

至此我們就可以在頁(yè)面上看到地圖的展示了,打開控制臺(tái)我們也可以看到對(duì)地圖瓦片的請(qǐng)求,請(qǐng)求的是maps/9目錄下的瓦片,我們也能注意到,有一些404的請(qǐng)求,這是因?yàn)関iew圖層中的部分地圖瓦片我們沒(méi)有準(zhǔn)備,通過(guò)在頁(yè)面上檢查元素,也可以看到map容器中確實(shí)存在一部分沒(méi)有貼上瓦片,這通常來(lái)說(shuō)沒(méi)什么關(guān)系,可以不用管;可以看到當(dāng)使用鼠標(biāo)滾動(dòng)縮放地圖的時(shí)候,也會(huì)去請(qǐng)求相應(yīng)縮放比例的地圖瓦片。

  • 添加簡(jiǎn)單的交互事件
    最后來(lái)添加一些簡(jiǎn)單的交互。
    之前我做的需求中需要根據(jù)接口返回的數(shù)據(jù)批量標(biāo)注地圖上的點(diǎn),但是因?yàn)楝F(xiàn)在沒(méi)有數(shù)據(jù),這里就實(shí)現(xiàn)一些簡(jiǎn)單的交互吧。

    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));
    });
    

    我們可以通過(guò)zoom獲取視圖的縮放級(jí)別,通過(guò)extent獲取視圖的經(jīng)緯度范圍,還可以進(jìn)一步通過(guò)extent的getTopLeft和getBottomRight分別獲取左上角的經(jīng)緯度和右下角的經(jīng)緯度;這樣我們就可以在縮放視圖和移動(dòng)圖層時(shí)根據(jù)視圖的經(jīng)緯度范圍來(lái)加載相應(yīng)的數(shù)據(jù)。

    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); // 獲取坐標(biāo)
    
        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);
    });
    

    我們還可以在處理地圖的鼠標(biāo)點(diǎn)擊事件時(shí),獲取鼠標(biāo)點(diǎn)對(duì)應(yīng)的經(jīng)緯度,通過(guò)Feature類給地圖添加標(biāo)注,再通過(guò)Style類給標(biāo)注設(shè)置樣式;也可以在添加新標(biāo)注前移除舊的標(biāo)注。

    const layers = map.getLayers();
    layers.forEach(item => {
      if(item instanceof VectorLayer) map.removeLayer(item);
    });
    

到這里我們就完成了OpenLayers的簡(jiǎn)單使用,如果有感興趣的小伙伴,可以去OpenLayers的GitHub和官方文檔再去進(jìn)一步的了解。

以下是運(yùn)行效果:

整體代碼參考這個(gè)CodePen

總結(jié)

以上是生活随笔為你收集整理的开源地图库OpenLayers的简单使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。