vue+cesium加載DEM和GeoServer服務


1、開發環境介紹

1.1 node.js

版本:v14.17.3

Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行時,而cesium必須要部署web服務器才可以運行,因此使用node.js作為開發服務器,node.js需要在網站上下載本地安裝包進行安裝並部署環境變量。

1.2 vue

版本:v2.6.11

Vue (讀音 /vjuː/,類似於 view) 是一套用於構建用戶界面的漸進式javascript框架。筆者因為對本框架比較熟悉,因此使用本JS框架來搭建本次環境。

1.3 vue-cli

版本:v4.5.0

Vue CLI 是一個基於 Vue.js 進行快速開發的完整系統,提供:

  • 通過 @vue/cli 實現的交互式的項目腳手架。
  • 通過 @vue/cli + @vue/cli-service-global 實現的零配置原型開發。
  • 一個運行時依賴 (@vue/cli-service)

1.4 Cesium

版本:v1.87.1

Cesium是國外一個基於JavaScript編寫的使用WebGL的地圖引擎。Cesium支持3D,2D,2.5D形式的地圖展示,可以自行繪制圖形,高亮區域,並提供良好的觸摸支持,且支持絕大多數的瀏覽器和mobile。

1.5 GeoServe

版本:2.20.1

GeoServer是一個基於Java的軟件服務器,允許用戶查看和編輯地理空間數據。 類似於IIS和tomcat的作用,不過GeoServer是專門用於空間數據的服務器。GeoServer需要基於JAVA環境。

1.6 vscode

VSCode(全稱:Visual Studio Code)是一款由微軟開發且跨平台的免費源代碼編輯器

2、部署開發環境

2.1 安裝node.js

下載安裝包后安裝即可,略過。

2.2 安裝vue.js

在vscode或cmd終端中。

npm install vue -g

2.3 安裝vue腳手架

在vscode或cmd終端中。

npm install vue-cli -g

2.4 創建項目

  • npx vue create 項目名稱

  • 選擇vue2項目

  • 安裝cesium至當前項目下

    npm install cesium --save

2.5 配置cesium

設置cesium相關的webpack配置:

  • 建立一個vue.config.js文件

    const path = require("path");
    const TerserPlugin = require('terser-webpack-plugin');
     
    const CopyWebpackPlugin = require('copy-webpack-plugin');
    const webpack = require('webpack');
    const cesiumSource = './node_modules/cesium/Source'
     
    function resolve(dir) {
      return path.join(__dirname, dir);
    }
     
    module.exports = {
      // 打包后運行環境目錄
      publicPath: process.env.NODE_ENV === "production" ? "/projectName/" : "/",
     
      lintOnSave: true, // eslint-loader 是否在保存的時候檢查
      productionSourceMap: false, // 生產環境是否生成 sourceMap 文件
      filenameHashing: true, // 文件hash
      /*
        配置vue-cli3項目,可以說是all in vue.config.js的。
        當然,封裝、就一定會留個口給用戶,去對底層進行自定義操作。
        vue.config.js的配置項中,有兩個口,configureWebpack和chainWebpack。
        configureWebpack:
            是調整webpack配置最簡單的一種方式,可以新增也可以覆蓋cli中的配置。
        可以是一個對象:被 webpack-merge 合並到webpack 的設置中去
        也可以是一個函數:如果你需要基於環境有條件地配置行為,就可以進行一些邏輯處理,可以直接修改或
        新增配置,(該函數會在環境變量被設置之后懶執行)。該方法的第一個參數會收到已經解析好的配置。
        在函數內,你可以直接修改配置,或者返回一個將會被合並的對象。
        chainWebpack:
            這個庫提供了一個 webpack 原始配置的上層抽象,使其可以定義具名的 loader 規則
        和具名插件,可以通過其提供的一些方法鏈式調用,在cli-service中就使用了這個插件
      */
      configureWebpack: {
        output: {
          sourcePrefix: ' ' // 1 讓webpack 正確處理多行字符串配置 amd參數
        },
        amd: { // 2
          toUrlUndefined: true // webpack在cesium中能友好的使用require
        },
        resolve: {
          extensions: ['.js', '.vue', '.json'],
          alias: {
            'cesium': path.resolve(__dirname, cesiumSource) // 3 定義別名cesium后,cesium代表了cesiumSource的文件路徑
          }
        },
        plugins: [ // 4、配置webpack直接復制
          new CopyWebpackPlugin([{ from: path.join(cesiumSource, 'Workers'), to: 'Workers' }]),
          new CopyWebpackPlugin([{ from: path.join(cesiumSource, 'Assets'), to: 'Assets' }]),
          new CopyWebpackPlugin([{ from: path.join(cesiumSource, 'Widgets'), to: 'Widgets' }]),
          new CopyWebpackPlugin([{ from: path.join(cesiumSource, 'ThirdParty/Workers'), to: 'ThirdParty/Workers' }]),
          new webpack.DefinePlugin({ // 5
            CESIUM_BASE_URL: JSON.stringify('./')
          })
        ],
        // module: {
        //   unknownContextRegExp: /^.\/.*$/,
        //   unknownContextCritical: false // 6 不讓webpack打印載入特定庫時候的警告
        // }
        optimization: {
          minimizer: [
            new TerserPlugin({
              terserOptions: {
                ecma: undefined,
                warnings: false,
                parse: {},
                compress: {
                  drop_console: true,
                  drop_debugger: false,
                  pure_funcs: ['console.log'] // 移除console
                }
              },
            }),
          ]
        },
      },
     
      chainWebpack: config => {
        // 配置import 和 require 等路徑別名,webpack中是通過 resolve.alias 來實現此功能的,通過set方法添加修改想要的alias 配置
        config.resolve.alias
          .set("@", resolve("src"))
          .set("spatial", resolve("public/SpatialData"))
          .set("assets", resolve("src/assets"))
          .set("components", resolve("src/components"));
      },
     
      // 修改瀏覽中的標簽logo
      pwa: {
        iconPaths: {
          favicon32: "favicon.ico",
          favicon16: "favicon.ico",
          appleTouchIcon: "favicon.ico",
          maskIcon: "favicon.ico",
          msTileImage: "favicon.ico"
        }
      },
     
      // 多頁面方式
      // pages: {
      //   index: {
      //     entry: './src/main',
      //     template: './public/index.html',
      //     fileName: 'index.html',
      //   },
      //   weui: {
      //     entry: './src/wmain',
      //     template: './public/windex.html',
      //   }
      // },
     
      css: {
        loaderOptions: {
          sass: {
            // implementation: require('sass'), // This line must in sass option
            // prependData: `@import "@/assets/scss/mixin.scss";` //引入全局變量
          },
        },
      },
     
    };
    
  • 由於在./node_modules/cesium/Source/ThirdParty/zip.js 文件中使用了 import.meta 語法,因此我們需要安裝loader

    npm install @open-wc/webpack-import-meta-loader --save-dev

    安裝好了以后繼續在vue.config.js中添加(在plugins[…]后面)loader的相關配置。

    module: {
          rules: [
          {
          test: /\.js$/,
          use: {
          loader: '@open-wc/webpack-import-meta-loader',
          },
          },
        ]}
    

2.6 部署初始地圖界面

  • 完成cesium相關配置后,在mani.js中掛載cesium到vue.prototype上

    import Vue from 'vue'
    import App from './App.vue'
    
    // 引入cesium相關文件
    var cesium = require('cesium/Cesium.js');
    var widgets = require('cesium//Widgets/widgets.css');
    
    Vue.config.productionTip = false
    //將cesium對象掛載到vue原型上
    Vue.prototype.cesium = cesium
    Vue.prototype.widgets = widgets
    
    new Vue({
      render: h => h(App),
    }).$mount('#app')
    
  • 在manin.JS掛載的APP.vue上導入HelloWord.vue組件並清空其他內容

    <template>
      <div id="app">
        <HelloWorld />
      </div>
    </template>
    
    <script>
    import HelloWorld from './components/HelloWorld.vue'
    
    export default {
      name: 'App',
      components: {
        HelloWorld
      }
    }
    </script>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    
    
  • 修改helloWord.Vue的代碼

    <template>
     <div id="container" class="box">
        <div id="cesiumContainer"></div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
       methods: {
        init () {
          const Cesium = this.cesium//獲取原型中的Cesium對象
          const viewer = new Cesium.Viewer('cesiumContainer');//創建地圖對象,掛載至模板中
          viewer._cesiumWidget._creditContainer.style.display = "none";// 隱藏版權
        }
      },
      mounted () {
        this.init()
      }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    html,
    body,
    #cesiumContainer {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      overflow: hidden;
    }
    .box {
      height: 100%;
    }
    </style>
    
    
  • 使用npm dev serve在本地啟動項目,效果如下。

3、DEM地形加載

3.1 cesium實驗室安裝

  • Cesiumlab是一款專為Cesium開源數字地球平台打造的免費數據處理工具集。我們可以使用它將DEM數據切片及發布服務,下載地址:http://www.cesiumlab.com/。

  • 安裝完成后啟動Cesiumlab,將會啟動一個web服務器和一個可視化操作界面(網頁)

    操作界面:

    image-20211119174149215

    使用手機號碼注冊登錄后即可進行數據切片及服務發布。

3.2 DEM切片及服務發布

  • 如下圖,輸入文件為TIF格式的DEM影像,輸入前在ARCGIS中檢查坐標系信息是否齊全,DEM是否正常顯示。

    image-20211119101946189

  • 下圖為切片過程進程,切片完成后將在web服務器自動發布該DEM切片服務。

    image-20211119102046216

  • 切片完成后進入服務列表查看:

    image-20211119174709771

  • 通過右側的預覽圖標可進入cesium服務預覽界面,影像服務的加載速度極大影響切片速度,建議將底圖修改為arcgis在線影像或其他加載速度較快的影像。

    image-20211119175110750

3.3 在地圖中添加地形圖服務

  • cesium中管理地形服務的對象為:CesiumTerrainProvider,在應用創建的生命周期中通過該類創建地形對象(HelloWord.vue中)。

    const terrainProvider = new Cesium.CesiumTerrainProvider({
          url: 'http://localhost:9003/terrain/GPFHT7F4/'
          });
          viewer.terrainProvider = terrainProvider;
    
  • 再通過之前創建的地圖對象將地形掛載viewer.terrainProvider = terrainProvider;

  • 將相機位置控制到DEM所在位置

    viewer.camera.flyTo({
              destination:Cesium.Cartesian3.fromDegrees(115.601, 29.105, 15000.0)
            });
    

    整個HelloWord.vue代碼如下:

    <template>
     <div id="container" class="box">
        <div id="cesiumContainer"></div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'HelloWorld',
       data(){
    
       },
       methods: {
        init () {
          const Cesium = this.cesium
          const viewer = new Cesium.Viewer('cesiumContainer' );
          //CesiumTerrainProvider函數是cesium中地形圖的函數
          const terrainProvider = new Cesium.CesiumTerrainProvider({
          url: 'http://localhost:9003/terrain/GPFHT7F4/'
          });
          viewer.terrainProvider = terrainProvider;
          //控制相機位置 
          viewer.camera.flyTo({
              destination:Cesium.Cartesian3.fromDegrees(115.601, 29.105, 15000.0)
            });
    
          viewer._cesiumWidget._creditContainer.style.display = "none";// 隱藏版權
        }
      },
      mounted () {
        this.init()
      }
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    html,
    body,
    #cesiumContainer {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      overflow: hidden;
    }
    .box {
      height: 100%;
    }
    </style>
    
    

3.4 啟動服務

  • 使用npm run serve命令啟動服務,在LOCALHOST:8080中打開,縮放至地形變化明顯的地方即可看見DEM渲染。

    image-20211119182230900

4、GeoServer服務發布、調用

4.1 安裝GeoServer

GeoServer基於Java開發,因此安裝前必須確保安裝了Java。

官網http://geoserver.org/download/下載穩定版,文中使用2.20.0。

除了端口號要單獨設置,其他的設置都接受默認值即可。

安裝完成后,在左下角程序中選擇Start GeoServer即可啟動服務,進入http://localhost:8010/geoserver(端口號按安裝時選擇變化)。

image-20211121214820067

4.2 發布地理數據服務

首先創建一個工作區,並啟用工作區。

image-20211121215725062

再選擇數據源,添加一個新的數據源

image-20211121215803115

選擇shapefile矢量數據源:

image-20211121215839316

選擇數據路徑並保存關閉:

image-20211121220630129

再進入圖層預覽就能看見我們發布的數據圖層了,由於GeoServer不支持WFS服務,因此我們使用WMS(選擇png圖片)先進行展示

image-20211121220814849

彈出的網頁中,就是我們的服務地址了。

image-20211121220922161

4.3 解決跨域問題

跨域問題的本質是現代瀏覽器對網站的一種保護,禁止在A處獲取的HTML頁面里去調取B處的資源,A和B是否一處的定義是http(協議)IP(或域名)端口號都完全一致,如下例:

在我們的GeoServer服務的搭建時,我們在cesium的頁面中(http://localhost:8080/)獲取地圖數據(http://localhost:8091/geoserver/cite/wms)時,就面臨了端口不一致的問題,但是端口又不能重復使用,因此必須跨域問題必須解決。

而通過cesium實驗室發布的數據沒有這個問題,應該是cesium實驗室已經做過處理了。

我們通過打開cesium實驗室的請求數據瓦片,看到Headers(請求頭)中已經攜帶了Access-Control-Allow-Origin: *的信息,即聲明本請求不需要受到保護。

image-20211122183255458

解決這個問題的辦法就是像cesium在請求B處資源時,帶上請求頭,而在geoServer中我們想要帶上這個請求頭需要去做如下處理:

  • 下載跨域jar包並將jar包放到Geoserver安裝目錄 \webapps\geoserver\WEBINF\lib文件夾下(GeoServer版本2.20.0,jar包版本對應v20180830)。

  • jar包鏈接:https://pan.baidu.com/s/1_t4yaCrVQxOyYmg2yFiyhQ
    提取碼:8888

  • 設置跨域配置。打開Geoserver安裝目錄 \webapps\geoserver\WEBINF\web.xml文件,找到文件中<!-- Uncomment following filter toenable CORS的位置,把跨域配置的注釋放開。

    image-20211122184507303

    image-20211122184518153

  • 重啟GeoServe服務

4.4 調用地圖服務

在地圖組件的初始化方法中新建一個Cesium.WebMapServiceImageryProvider對象來對承載服務。

var imageryProvider1=new Cesium.WebMapServiceImageryProvider({
                url:'http://localhost:8010/geoserver/cite/wms',
                  //layers:['0','1'],
                 layers:'cite:S215',
                 parameters : {
                 service : 'WMS',
                 format: 'image/png',
                 transparent:true,
                 //show:false
                },
              });

在地圖中添加本對象:

Viewer.imageryLayers.addImageryProvider(imageryProvider1);

再次進入工程后,效果如下:

image-20211121221528604


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM