Vue+Webpack+OpenLayers6完成組件化的WebGIS開發(二、組件化開發WebGIS實例)

上一章我們搭建了vue-cli,npm等環境,並且基於組件化開發的模式藉助vue+webpack+openlayers6實現了地圖的加載。今天這一章,我們將繼續組件化的開發地圖相關功能,我會通過具體的地圖功能實例來進行闡述,大家加油!

這裏把上一章內容鏈接發一下:https://blog.csdn.net/MagicMHD/article/details/104962747

一、地圖雙屏聯動功能的開發

1、在上一章新建的項目的基礎上添加一個DoubleMap組件如下圖:

2、編寫DoubleMap組件完成雙屏聯動效果,代碼如下:

<template>
      <div>
            <p>地圖1</p>
            <div id="map1"></div>
            <p>地圖2</p>
             <div id="map2"></div>
      </div>
</template>
<script>
import 'ol/ol.css'
import View from 'ol/View'
import Map from 'ol/Map'
import TileLayer from 'ol/layer/Tile'
import {OSM, TileArcGISRest} from 'ol/source';
export default {
    name:'OlMap',
    mounted() {   
      //渲染地圖
      //1、首先創建一個視圖
      var view=new View({
            center: [0, 0],
            zoom: 2
      })
      //2、創建地圖圖層
      var layers1=[
            new TileLayer({
                  source: new OSM()
            })
      ]
      var layers2=[
            new TileLayer({
                  source: new OSM()
            })
      ]
      //3、創建第一個地圖
      var map1=new Map({
             target: 'map1',
             layers: layers1,
             view: view
      })   
      //4、創建第二個地圖
      var map2=new Map({
            layers: layers2,
            target: 'map2',
            view: view
      })
    }     

}
</script>
<style lang="stylus" scoped>
#map1
      width:600px
      height:250px
#map2
      width:600px
      height:250px
</style>

這裏我們新建了兩個map,但是讓兩個map共用一個view,這樣就可以達到雙屏聯動的效果,如果你只是想雙屏展示,不想聯動,那就讓兩個map分別對應不同的view即可。

3、調用DoubleMap組件完成地圖雙屏聯動

首先我們要在Home組件裏面引入DoubleMap局部組件,包括:引入DoubleMap組件、聲明局部組件和最後在模板中使用局部組件這三步,Home.vue組件的具體代碼如下:

<template>
  <!-- 這裏我們就可以用引入的HomeMap組件了,大小寫用破折號 -->
    <home-double-map></home-double-map>
</template>

<script>
// 首先引入局部組件
import HomeMap from './components/Map'
import HomeDoubleMap from './components/DoubleMap'
export default {
  name: 'Home',
  // 需要聲明局部組件
  components: {
    HomeMap: HomeMap,
    HomeDoubleMap: HomeDoubleMap
  }
}
</script>

<style scoped>
</style>

這裏面還有上一章引入的Map組件,我沒刪除但是在模板template裏面只用了DoubleMap組件,所以程序界面也就只會顯示地圖雙屏聯動的功能了!

4、運行程序測試

效果如下圖所示:

當我們移動一個地圖時,另外一個地圖也會移動,也就實現了地圖聯動功能!

二、地圖上下左右移動及定位功能

1、新建MapLoc組件,如下圖所示:

2、編寫MapLoc組件,使之完成地圖上下左右移動及定位功能,代碼如下:

<template>
      <div>
            <div>
                  <div id="map"></div>
            </div>

            <div>
                  <button @click="moveToLeft">左移</button>
                  <button @click="moveToRight">右移</button>
                  <button @click="moveToUp">上移</button>
                  <button @click="moveToDown">下移</button>
                  <button @click="moveToQingdao">移到青島</button>
                  <button @click="zoomIn">放大</button>
                   <button @click="zoomOut">縮小</button>
            </div>  
      </div>
</template>
<script>
import 'ol/ol.css'
import View from 'ol/View'
import Map from 'ol/Map'
import TileLayer from 'ol/layer/Tile'
import  {transform} from 'ol/proj';
import {OSM, TileArcGISRest} from 'ol/source'
export default {
    name:'OlMapLoc',
    data() {
          return {
                map: null,
                view: null,
                layers: null
          }
    },
    mounted() {   
      //渲染地圖
      //1、首先創建一個視圖
      var view=new View({
             // 設置青島爲地圖中心,此處進行座標轉換, 把EPSG:4326的座標,轉換爲EPSG:3857座標,因爲ol默認使用的是EPSG:3857座標
            center: transform([120.374798,36.07316], 'EPSG:4326', 'EPSG:3857'),
            zoom: 10
      })
    
      //2、創建地圖圖層
      var layers=[
            new TileLayer({
                  source: new OSM()
            })
      ]     
      //3、創建地圖
      var map=new Map({
             target: 'map',
             layers: layers,
             view: view
      })   
      this.map=map;
      this.view=view;
      this.layers=layers;
    },
    methods: {
          //左移
          moveToLeft: function(e){                 
            var view = this.map.getView();
            var mapCenter = this.view.getCenter();
            // 讓地圖中心的x值增加,即可使得地圖向左移動,增加的值根據效果可自由設定
            mapCenter[0] += 50000;
            view.setCenter(mapCenter);
            this.map.render();
          },
          //右移
          moveToRight: function(e){
            var view = this.map.getView();
            var mapCenter = this.view.getCenter();
            // 讓地圖中心的x值減少,即可使得地圖向右移動,增加的值根據效果可自由設定
            mapCenter[0] -= 50000;
            view.setCenter(mapCenter);
            this.map.render();
          },
          //上移
          moveToUp: function(e){
            var view = this.map.getView();
            var mapCenter = this.view.getCenter();
            // 讓地圖中心的y值減少,即可使得地圖向上移動,增加的值根據效果可自由設定
            mapCenter[1] -= 50000;
            view.setCenter(mapCenter);
            this.map.render();
          },
          //下移
           moveToDown: function(e){
            var view = this.map.getView();
            var mapCenter = this.view.getCenter();
            // 讓地圖中心的y值增加,即可使得地圖向下移動,增加的值根據效果可自由設定
            mapCenter[1] += 50000;
            view.setCenter(mapCenter);
            this.map.render();
          },
          //移動到青島
          moveToQingdao: function(e){
            var view = this.map.getView();
            // 設置地圖中心爲青島的座標,即可讓地圖移動到青島
            view.setCenter(transform([120.374798,36.07316], 'EPSG:4326', 'EPSG:3857'));
            this.map.render();
          },
          //放大
          zoomIn: function(e){
            var view = this.map.getView();
            // 讓地圖的zoom增加1,從而實現地圖放大
            view.setZoom(view.getZoom() + 1);
          },
           //縮小
          zoomOut: function(e){
            var view = this.map.getView();
            // 讓地圖的zoom增加1,從而實現地圖縮小
            view.setZoom(view.getZoom() - 1);
          }
    }     

}
</script>
<style lang="stylus" scoped>
#map
      width:900px
      height:350px
</style>

這裏說一下由於我們在做地圖操作時一般都會涉及map、view、layer等操作,爲了方便獲取這些對象,我們把這些對象放到data方法裏面,初始化地圖的時候使用this方法給這些參數賦值,在操作地圖的時候只需要使用this指向這些參數就可以。說白了就是給這些參數定義全局變量,使我們方便使用!

3、調用MapLoc組件完成地圖雙屏聯動

首先我們要在Home組件裏面引入MapLoc局部組件,包括:引入MapLoc組件、聲明局部組件和最後在模板中使用局部組件這三步,Home.vue組件的具體代碼如下:

<template>
  <!-- 這裏我們就可以用引入的HomeMap組件了,大小寫用破折號 -->
    <home-map-loc></home-map-loc>
</template>

<script>
// 首先引入局部組件
import HomeMap from './components/Map'
import HomeDoubleMap from './components/DoubleMap'
import HomeMapLoc from './components/MapLoc'
export default {
  name: 'Home',
  // 需要聲明局部組件
  components: {
    HomeMap: HomeMap,
    HomeDoubleMap: HomeDoubleMap,
    HomeMapLoc: HomeMapLoc
  }
}
</script>

<style scoped>
</style>

4、運行程序測試,如下圖:

經過測試上述功能都沒有問題!

三、 加載各種在線地圖

這一部分我們要實現一些常見的在線地圖的加載,比如ArcGIS地圖服務、OSM地圖服務、天地圖服務和高德地圖服務。並且實現這些圖層的疊加順序的相關操作!

1、新建MapOnline組件,如下圖所示:

2、編寫MapOnline組件,使之可以加載常用的在線地圖,代碼如下:

<template>
      <div>
            <div>
                  <div id="map"></div>
            </div>
            <div>顯示/隱藏:   
                  <input type="checkbox" checked="checked" @click="checkERSI($event)" />加載ArcGIS地圖
                  <input type="checkbox" checked="checked" @click="checkOSM($event)"/>加載Open Street Map地圖
                  <input type="checkbox" checked="checked" @click="checkTDT($event)"/>加載天地圖
                  <input type="checkbox" checked="checked" @click="checkAmap($event)"/>加載高德地圖 -->
            </div> 
            <div>圖層順序:
                  <input name="seq" type="radio" value="" @click="upArcGIS($event);" />ArcGIS地圖在最上
                  <input name="seq" type="radio" value=""  @click="upOSM($event);"/>OSM地圖在最上
                  <input name="seq" type="radio" value="" checked="checked" @click="upTDT($event);"/>天地圖在最上
                  <input name="seq" type="radio" value="" checked="checked" @click="upAmap($event);"/>高德地圖在最上
            </div> 
      </div>
</template>
<script>
import 'ol/ol.css'
import View from 'ol/View'
import Map from 'ol/Map'
import TileLayer from 'ol/layer/Tile'
// import {Group as LayerGroup, Tile as TileLayer} from 'ol/layer'
import  {transform} from 'ol/proj';
import {OSM, TileArcGISRest, XYZ} from 'ol/source'
export default {
    name:'OlMapOnline',
    data() {
          return {
                map: null,
                view: null,
                //這裏創建我們要添加的多個圖層
                esriLayers: null,
                osmLayers: null,
                tiandituLayers: null,
                gaodeLayers: null
          }
    },
    mounted() {   
      //渲染地圖
      //1、首先創建一個視圖
      var view=new View({
             // 設置青島爲地圖中心,此處進行座標轉換, 把EPSG:4326的座標,轉換爲EPSG:3857座標,因爲ol默認使用的是EPSG:3857座標
            center: transform([120.374798,36.07316], 'EPSG:4326', 'EPSG:3857'),
            zoom: 10
      })
      this.view=view;
      //2、創建地圖圖層
      var esriLayers=
            new TileLayer({
                  source: new XYZ({
                        url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'
                  }),
                  title: 'ESRI影像'
            })
      
      //給data中的esriLayers賦值
      this.esriLayers=esriLayers;
      var osmLayers=
            new TileLayer({
                  source: new OSM(),
                  title: 'OSM影像'
            })
       
      this.osmLayers=osmLayers;
      var tiandituLayers=
            new TileLayer({
                  source: new XYZ({
                       	url: "http://t3.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=008a8816d2eee25a677670273eaee891",
      	            crossOrigin: "anonymous"
                  }),
                  title: '天地圖影像'
            })
       
      //給data賦值
      this.tiandituLayers=tiandituLayers;
      var gaodeLayers=
            new TileLayer({
                  source: new XYZ({
                       	url:'http://webst0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}'
                  }),
                  title: '高德影像'
            })
       
      //給data賦值
      this.gaodeLayers=gaodeLayers;

      //3、創建地圖
      var map=new Map({
             target: 'map',
             //// 在地圖上添加上面創建的四個圖層,圖層順序自下而上,依次是ESRI地圖,OSM地圖,天地圖和高德地圖
             layers: [esriLayers,osmLayers,tiandituLayers,gaodeLayers],
             view: view
      })
      this.map=map;

     
    },
    methods: {
         checkERSI: function(event){
            console.log(event.target.checked)
            this.esriLayers.setVisible(event.target.checked);
         },
         checkOSM: function(event){
            this.osmLayers.setVisible(event.target.checked);
         },
         checkTDT: function(event){
            this.tiandituLayers.setVisible(event.target.checked);
         },
         checkAmap: function(event){
            this.gaodeLayers.setVisible(event.target.checked);
         },
         upArcGIS: function(event){
            if(event.target.checked){
                   this.esriLayers.setZIndex(3);
                   this.osmLayers.setZIndex(this.osmLayers.getZIndex()-1);
                  this.tiandituLayers.setZIndex(this.tiandituLayers.getZIndex()-1);
                   this.gaodeLayers.setZIndex(this.gaodeLayers.getZIndex()-1);
            }
         },
         upOSM: function(event){
            if(event.target.checked){
                   this.osmLayers.setZIndex(3);
                   this.esriLayers.setZIndex(this.esriLayers.getZIndex()-1);
                  this.tiandituLayers.setZIndex(this.tiandituLayers.getZIndex()-1);
                   this.gaodeLayers.setZIndex(this.gaodeLayers.getZIndex()-1);
            }
         },
         upTDT: function(event){
           if(event.target.checked){
                   this.tiandituLayers.setZIndex(3);
                   this.esriLayers.setZIndex(this.esriLayers.getZIndex()-1);
                  this.osmLayers.setZIndex(this.osmLayers.getZIndex()-1);
                   this.gaodeLayers.setZIndex(this.gaodeLayers.getZIndex()-1);
            }    
         },
         upAmap: function(event){
            if(event.target.checked){
                   this.gaodeLayers.setZIndex(3);
                  this.esriLayers.setZIndex(this.esriLayers.getZIndex()-1);
                  this.osmLayers.setZIndex(this.osmLayers.getZIndex()-1);
                   this.tiandituLayers.setZIndex(this.tiandituLayers.getZIndex()-1);
            } 
         }
        
    }     

}
</script>
<style lang="stylus" scoped>
#map
      width:900px
      height:350px
</style>

3、調用MapOnline組件完成地圖雙屏聯動

首先我們要在Home組件裏面引入MapOnline局部組件,包括:引入MapOnline組件、聲明局部組件和最後在模板中使用局部組件這三步,Home.vue組件的具體代碼如下:

<template>
  <!-- 這裏我們就可以用引入的HomeMap組件了,大小寫用破折號 -->
    <home-map-online></home-map-online>
</template>

<script>
// 首先引入局部組件
import HomeMap from './components/Map'
import HomeDoubleMap from './components/DoubleMap'
import HomeMapLoc from './components/MapLoc'
import HomeMapOnline from './components/MapOnline'
export default {
  name: 'Home',
  // 需要聲明局部組件
  components: {
    HomeMap: HomeMap,
    HomeDoubleMap: HomeDoubleMap,
    HomeMapLoc: HomeMapLoc,
    HomeMapOnline: HomeMapOnline
  }
}
</script>

<style scoped>
</style>

4、運行測試

經過測試,以上功能均沒有問題!

 四、加載我們自己發佈的地圖服務

這裏以加載Geoserver發佈的WMS服務爲例進行講解。關於Geoserver如何發佈地圖服務我之前在openlayers入門開發中做過一個詳細的說明,不明白的同學可以看一下,鏈接如下:https://blog.csdn.net/MagicMHD/article/details/91430148

好了,下面開始實際編碼加載Geoserver發佈的wms地圖服務了!

1、新建MapWms組件,如下圖所示

2、編寫MapWms組件,使之可以加載Geoserver發佈的wms地圖服務,代碼如下:

<template>
      <div>
            <div id="map"></div>
      </div>
</template>
<script>
import 'ol/ol.css'
import View from 'ol/View'
import Map from 'ol/Map'
import TileLayer from 'ol/layer/Tile'
import Projection from 'ol/proj/Projection';
import TileWMS from 'ol/source/TileWMS';
import {OSM} from 'ol/source'
export default {
    name:'OlMapWms',
    data() {
          return {
                map: null,
                view: null,
                //這裏創建我們要添加的圖層
                chinaLayers: null
          }
    },
    mounted() {   
      //渲染地圖

      //1、創建wms地圖圖層
      var chinaLayers=
            new TileLayer({
                  source: new TileWMS({
                       	url: "http://"這裏要寫你實際發佈地圖服務的IP地址":8123/geoserver/airtraffic/wms",
      	            params: {
                              'FORMAT': 'image/png', 
                              'VERSION': '1.1.1',
                              tiled: true,
                              STYLES: '',
                              LAYERS: 'airtraffic:china',
                              tilesOrigin: 73.62004852302096 + "," + 3.8378885148431436
                        }
                  }),
                  title: '中國wms服務'
            })      
      //給data賦值
      this.chinaLayers=chinaLayers;

      //2、創建空間參考4326
      var projection = new Projection({
          code: 'EPSG:4326',
          units: 'degrees', 
      });

      //3、創建視圖
      var view=new View({
            projection: projection
      })
      this.view=view;

      //4、創建地圖
      var map=new Map({
             target: 'map',
             layers: [chinaLayers],
             view: view
      })

      var bounds = [73.62004852302096, 3.8378885148431436,
                    134.7684631352655, 53.553741455004214];
      map.getView().fit(bounds, map.getSize());
    }

}
</script>
<style lang="stylus" scoped>
#map
      width:900px
      height:350px
</style>

3、調用MapWms組件完成地圖雙屏聯動

首先我們要在Home組件裏面引入MapWms局部組件,包括:引入MapWms組件、聲明局部組件和最後在模板中使用局部組件這三步,Home.vue組件的具體代碼如下:

<template>
  <!-- 這裏我們就可以用引入的HomeMap組件了,大小寫用破折號 -->
    <home-map-wms></home-map-wms>
</template>

<script>
// 首先引入局部組件
import HomeMap from './components/Map'
import HomeDoubleMap from './components/DoubleMap'
import HomeMapLoc from './components/MapLoc'
import HomeMapOnline from './components/MapOnline'
import HomeMapWms from './components/MapWms'
export default {
  name: 'Home',
  // 需要聲明局部組件
  components: {
    HomeMap: HomeMap,
    HomeDoubleMap: HomeDoubleMap,
    HomeMapLoc: HomeMapLoc,
    HomeMapOnline: HomeMapOnline,
    HomeMapWms: HomeMapWms
  }
}
</script>

<style scoped>
</style>

4、運行測試

這裏我們就成功的把Geoserver發佈的wms服務加載出來了!

五、加載離線矢量地圖數據

這裏以加載GeoJSON數據爲例進行講解!

1、新建MapJson組件,如下圖所示

 

2、編寫MapJson組件,使之可以加載GeoJSON數據,代碼如下:

<template>
      <div>
            <div id="map"></div>
      </div>
</template>
<script>
import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import GeoJSON from 'ol/format/GeoJSON';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import {Fill, Stroke, Style, Text} from 'ol/style';
export default {
    name:'OlMapWms',
    mounted() {   
          var vectorLayer = new VectorLayer({
            source: new VectorSource({
                  url: './../../../../static/china.json',
                  format: new GeoJSON()
            })
            });
            var map = new Map({
                  layers: [vectorLayer],
                  target: 'map',
                  view: new View({
                        center: [0, 0],
                        zoom: 1
                  })
             });
    }
}
</script>
<style lang="stylus" scoped>
#map
      width:900px
      height:350px
</style>

這裏要提醒大家的是json文件一定要放到static文件夾下,不然在Vue中是訪問不到的!這裏我踩了坑-。-

3、調用MapJson組件完成地圖雙屏聯動

首先我們要在Home組件裏面引入MapJson局部組件,包括:引入MapJson組件、聲明局部組件和最後在模板中使用局部組件這三步,Home.vue組件的具體代碼如下:

<template>
  <!-- 這裏我們就可以用引入的HomeMap組件了 -->
    <home-map-json></home-map-json>
</template>

<script>
// 首先引入局部組件
import HomeMap from './components/Map'
import HomeDoubleMap from './components/DoubleMap'
import HomeMapLoc from './components/MapLoc'
import HomeMapOnline from './components/MapOnline'
import HomeMapWms from './components/MapWms'
import HomeMapJson from './components/MapJson'
export default {
  name: 'Home',
  // 需要聲明局部組件
  components: {
    HomeMap: HomeMap,
    HomeDoubleMap: HomeDoubleMap,
    HomeMapLoc: HomeMapLoc,
    HomeMapOnline: HomeMapOnline,
    HomeMapWms: HomeMapWms,
    HomeMapJson: HomeMapJson
  }
}
</script>

<style scoped>
</style>

 

4、運行測試

加載成功!

 這裏就介紹這五種地圖的操作,如果你想詳細的瞭解OpenLayers的地圖操作,你可以看一下我之前根據原生js寫的openlayers的各種地圖操作,鏈接我就不給了,有好幾篇,你可以翻一下我的博客,截圖如下:

然後根據我們前面整理的基於vue+openlayers的模塊化地圖開發模式開發新的功能組件!其實原理掌握一點就行了,當你要使用openlayers的某個對象時,首先引用他,然後別的就和我們原聲js的openlayers操作基本一致了!

關於Vue+Webpack+OpenLayers6完成組件化的WebGIS開發的地圖實例講解就先講到這兒了!

下一章節我們將正式開始前後端分離+模塊化開發的WebGIS實戰項目的開發!我們現在有了中國的行政區劃數據,正好眼前全國正值抗擊新館疫情的關鍵時期,我們的實戰項目就以抗擊疫情爲主題!大家加油!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章