前后端分离的webgis项目(二)

1 篇文章 0 订阅
1 篇文章 0 订阅

前后端分离的webgis项目(二)

二. 前端vue+leaflet
首先你得安装nodejs并配置环境,看这里,然后安装vue-cli,用它来快速新建项目
可以使用下列任一命令安装

npm install -g @vue/cli
# OR
yarn global add @vue/cli

yarn如果没有,要先安装,yarn的安装包的速度比npm快,建议使用,用下面的命令安装,注意在前面参考的文章配置了global-folder和cache-folder,因此yarn安装后也要配置,看这里,不然会出问题

npm install -g yarn

vue-cli安装完后,使用可以使用vue -V或vue --version命令查看安装版本示意是否安装成功
在这里插入图片描述
接下来可以使用vue ui命令进行可视化创建,非常香,但是这里使用命令行创建项目,以便熟悉命令行操作
随意进入一个文件夹,cmd创建项目:vue create 你的项目名

vue create -n hello-world

在这里我加了一个参数-n用来跳过 git 初始化,详情参见官网

创建之后可以看到如下画面
在这里插入图片描述
第一个是我之前创建项目保留的项目配置,可以在你的C盘用户文件夹下的.vuerc文件查看和修改配置
第二个是默认配置
第三个是手动选择配置
这里选择第二个默认配置

项目新建完毕后,安装路由使用下面命令

yarn add vue-router

安装axios用于前后端通信

yarn add axios

之后安装leaflet依赖包

yarn add vue2-leaflet

最后安装leaflet地图控制依赖包,如果下载的依赖包地图不全,可以在网上搜索chinesetmsproviders,然后copy覆盖下载的依赖包

yarn add leaflet.chinesetmsproviders

项目的目录如下
在这里插入图片描述
main.js内容

import Vue from 'vue'
import App from './App.vue'
import 'leaflet/dist/leaflet.css'
import L from 'leaflet'
import router from './router'

Vue.prototype.$imgUrl = process.env.VUE_APP_IMAGES

Vue.config.productionTip = false

/* leaflet icon */
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
  iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
  iconUrl: require('leaflet/dist/images/marker-icon.png'),
  shadowUrl: require('leaflet/dist/images/marker-shadow.png'),
});

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')

.env.development内容

## 配置 正式接口地址
VUE_APP_URL = "http://localhost:8082"
VUE_APP_IMAGES = "http://localhost:8083"

vue.config.js内容

const path = require("path");
const sourceMap = process.env.NODE_ENV === "development";

module.exports = {
    // 基本路径
    publicPath: "./",
    // 输出文件目录
    outputDir: "dist",
    // eslint-loader 是否在保存的时候检查
    lintOnSave: false,
    // webpack配置
    // see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
    chainWebpack: () => {},
    configureWebpack: config => {
        if (process.env.NODE_ENV === "production") {
            // 为生产环境修改配置...
            config.mode = "production";
        } else {
            // 为开发环境修改配置...
            config.mode = "development";
        }

        Object.assign(config, {
            // 开发生产共同配置
            resolve: {
                extensions: [".js", ".vue", ".json", ".ts", ".tsx"],
                alias: {
                    vue$: "vue/dist/vue.js",
                    "@": path.resolve(__dirname, "./src")
                }
            }
        });
    },
    // 生产环境是否生成 sourceMap 文件
    productionSourceMap: sourceMap,
    // css相关配置
    css: {
        // 是否使用css分离插件 ExtractTextPlugin
        extract: true,
        // 开启 CSS source maps?
        sourceMap: false,
        // css预设器配置项
        loaderOptions: {},
        // 启用 CSS modules for all css / pre-processor files.
        modules: false
    },
    parallel: require("os").cpus().length > 1,
    pwa: {},
    // webpack-dev-server 相关配置
    devServer: {
        open: process.platform === "darwin",
        overlay: {
            warnings: false,
            errors: true
        },
        host: "localhost",
        port: 3001, //8080,
        https: false,
        hotOnly: false,
        proxy: {
            // 设置代理
            "/api": {
                target: process.env.VUE_APP_URL,
                changeOrigin: true,
                ws: true,
            }
        },
        before: app => {}
    },
};

VueLeaflet.vue内容

<template>
    <div class="vue-leaflet">
        <div class="map" ref="map"></div>
    </div>
</template>

<script>
    import { fetch } from "../utils/http-service";
    import 'leaflet.chinesetmsproviders'

    export default {
        name: "VueLeaflet",
        data() {
            return {
                map: '',
            };
        },
        mounted(){
            this.initMap();
            this.getSpot();

            window.addEventListener('scroll', function () {
                document.querySelector('body').setAttribute('style', 'margin: 0;')
            })
        },
        methods: {
            initMap(){
                const baselayers = this.addMulMap();
                const map =L.map(this.$refs.map, {
                    center: [28.22, 113.01],
                    zoom: 5,
                    layers: [baselayers.天地图],
                    zoomControl: false
                });
                this.map = map;
                L.control.zoom({
                    zoomInTitle: '放大',
                    zoomOutTitle: '缩小'
                }).addTo(map);

                L.control.layers(baselayers, null).addTo(map);
            },
            getSpot(){
                const map = this.map;
                const imgUrl = this.$imgUrl;
                const that = this;

                let naturalArr = [], cultureArr = [], parkArr = [], buildArr = [],
                    templeArr = [], ruinsArr = [], townsArr = [], cemeteryArr = [],
                    formerArr = [], religionArr = [];
                const result = fetch("/spot/virusdata");
                result.then(function (data) {
                    console.log(data);
                    for(let i=0; i<data.length; i++){
                        const t = data[i];
                        if(t.type==='自然风光'){
                            naturalArr.push(that.addToMarker(t, imgUrl));
                        }else if(t.type==='文化古迹'){
                            cultureArr.push(that.addToMarker(t, imgUrl));
                        }else if(t.type==='公园'){
                            parkArr.push(that.addToMarker(t, imgUrl));
                        }else if(t.type==='古建筑'){
                            buildArr.push(that.addToMarker(t, imgUrl));
                        }else if(t.type==='寺庙'){
                            templeArr.push(that.addToMarker(t, imgUrl));
                        }else if(t.type==='遗址'){
                            ruinsArr.push(that.addToMarker(t, imgUrl));
                        }else if(t.type==='古镇'){
                            townsArr.push(that.addToMarker(t, imgUrl));
                        }else if(t.type==='陵墓陵园'){
                            cemeteryArr.push(that.addToMarker(t, imgUrl));
                        }else if(t.type==='故居'){
                            formerArr.push(that.addToMarker(t, imgUrl));
                        }else if(t.type==='宗教'){
                            religionArr.push(that.addToMarker(t, imgUrl));
                        }
                    }
                    const naturalViews = L.layerGroup(naturalArr);
                    const cultureViews = L.layerGroup(cultureArr);
                    const parkViews = L.layerGroup(parkArr);
                    const buildViews = L.layerGroup(buildArr);
                    const templeViews = L.layerGroup(templeArr);
                    const ruinsViews = L.layerGroup(ruinsArr);
                    const townsViews = L.layerGroup(townsArr);
                    const cemeteryViews = L.layerGroup(cemeteryArr);
                    const formerViews = L.layerGroup(formerArr);
                    const religionViews = L.layerGroup(religionArr);
                    const overlayMaps = {
                        "自然风光": naturalViews,
                        "文化古迹": cultureViews,
                        "公园": parkViews,
                        "古建筑": buildViews,
                        "寺庙": templeViews,
                        "遗址": ruinsViews,
                        "古镇": townsViews,
                        "陵墓陵园": cemeteryViews,
                        "故居": formerViews,
                        "宗教": religionViews
                    };
                    map.addLayer(naturalViews);   // 默认添加自然风光景区到地图
                    L.control.layers(null, overlayMaps).addTo(map);
                })
            },
            addToMarker(t, imgUrl){
                const p = t.point.split(",");
                const lng = parseFloat(p[0]);
                const lat = parseFloat(p[1]);
                const l = L.marker([lat, lng]).bindPopup("<img alt="+t.name+" width='280' height='200' src="+imgUrl+"/"+t.data_id+".jpg"+"><h3>"+t.name+"</h3><span>"+t.level+" </span>" +
                    "<span>"+t.product_star_level+"</span><br/><span>类型:"+t.type+"</span><br/><span>地址:"+t.address+"</span><br/><span>"+t.intro+"</span>");
                return l;
            },
            addMulMap(){
                /**
                 * 智图地图内容
                 */
                const normalm1 = L.tileLayer.chinaProvider('Geoq.Normal.Map', {
                    maxZoom: 18,
                    minZoom: 5
                });
                const normalm3 = L.tileLayer.chinaProvider('Geoq.Normal.PurplishBlue', {
                    maxZoom: 18,
                    minZoom: 5
                });
                const normalm2 = L.tileLayer.chinaProvider('Geoq.Normal.Color', {
                    maxZoom: 18,
                    minZoom: 5
                });
                const normalm4 = L.tileLayer.chinaProvider('Geoq.Normal.Gray', {
                    maxZoom: 18,
                    minZoom: 5
                });
                const normalm5 = L.tileLayer.chinaProvider('Geoq.Normal.Warm', {
                    maxZoom: 18,
                    minZoom: 5
                });
                const normalm6 = L.tileLayer.chinaProvider('Geoq.Normal.Cold', {
                    maxZoom: 18,
                    minZoom: 5
                });
                /**
                 * 天地图内容
                 */
                const normalm = L.tileLayer.chinaProvider('TianDiTu.Normal.Map', {
                        maxZoom: 18,
                        minZoom: 5
                    }),
                    normala = L.tileLayer.chinaProvider('TianDiTu.Normal.Annotion', {
                        maxZoom: 18,
                        minZoom: 5
                    }),
                    imgm = L.tileLayer.chinaProvider('TianDiTu.Satellite.Map', {
                        maxZoom: 18,
                        minZoom: 5
                    }),
                    imga = L.tileLayer.chinaProvider('TianDiTu.Satellite.Annotion', {
                        maxZoom: 18,
                        minZoom: 5
                    });

                const normal = L.layerGroup([normalm, normala]),
                    image = L.layerGroup([imgm, imga]);
                /**
                 * 谷歌
                 */
                const normalMap = L.tileLayer.chinaProvider('Google.Normal.Map', {
                        maxZoom: 18,
                        minZoom: 5
                    }),
                    satelliteMap = L.tileLayer.chinaProvider('Google.Satellite.Map', {
                        maxZoom: 18,
                        minZoom: 5
                    });
                /**
                 * 高德地图
                 */
                const Gaode = L.tileLayer.chinaProvider('GaoDe.Normal.Map', {
                    maxZoom: 18,
                    minZoom: 5
                });
                const Gaodimgem = L.tileLayer.chinaProvider('GaoDe.Satellite.Map', {
                    maxZoom: 18,
                    minZoom: 5
                });
                const Gaodimga = L.tileLayer.chinaProvider('GaoDe.Satellite.Annotion', {
                    maxZoom: 18,
                    minZoom: 5
                });
                const Gaodimage = L.layerGroup([Gaodimgem, Gaodimga]);

                const baseLayers = {
                    "智图地图": normalm1,
                    "智图多彩": normalm2,
                    "智图午夜蓝": normalm3,
                    "智图灰色": normalm4,
                    "智图暖色": normalm5,
                    "智图冷色": normalm6,
                    "天地图": normal,
                    "天地图影像": image,
                    "谷歌地图": normalMap,
                    "谷歌影像": satelliteMap,
                    "高德地图": Gaode,
                    "高德影像": Gaodimage,
                };
                return baseLayers;
            }
        },
        //创建前设置
        beforeCreate () {
            document.querySelector('body').setAttribute('style', 'margin: 0;')
        },
        //销毁前清除
        beforeDestroy () {
            document.querySelector('body').removeAttribute('style')
        },
    };
</script>

<style scoped>
    .vue-leaflet {
        width: 100vw;
        height: 100vh;
        font-family: Avenir, Helvetica, Arial, sans-serif;
        -webkit-font-smoothing: antialiased;
        -moz-osx-font-smoothing: grayscale;
        text-align: center;
        color: #2c3e50;
        margin-top: 0;
    }
    .map{
        width: 100vw;
        height: 100vh;
    }
</style>

index.js内容

import Vue from 'vue'
import VueRouter from 'vue-router'
//自定义页面
import VueLeaflet from "../views/VueLeaflet";

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/vueLeaflet'   // 重定向
  },
  {
    path: '/vueLeaflet',
    name: 'vueLeaflet',
    component: VueLeaflet
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = new VueRouter({
  mode: 'hash',
  base: process.env.BASE_URL,
  routes
})

export default router

http-service.js内容

import axios from 'axios'

axios.defaults.timeout = 5000;  //请求超时设置
axios.defaults.baseURL = process.env.VUE_APP_URL

//http request 拦截器
axios.interceptors.request.use(
    config => {
        config.data = JSON.stringify(config.data);
        config.headers = {
            'Content-Type':'application/x-www-form-urlencoded'
        }
        return config;
    },
    error => {
        return Promise.reject(err);
    }
);

//响应拦截器即异常处理
axios.interceptors.response.use(response => {
    return response
}, err => {
    if (err && err.response) {
        switch (err.response.status) {
            case 400:
                console.log('错误请求')
                break;
            case 401:
                console.log('未授权,请重新登录')
                break;
            case 403:
                console.log('拒绝访问')
                break;
            case 404:
                console.log('请求错误,未找到该资源')
                break;
            case 405:
                console.log('请求方法未允许')
                break;
            case 408:
                console.log('请求超时')
                break;
            case 500:
                console.log('服务器端出错')
                break;
            case 501:
                console.log('网络未实现')
                break;
            case 502:
                console.log('网络错误')
                break;
            case 503:
                console.log('服务不可用')
                break;
            case 504:
                console.log('网络超时')
                break;
            case 505:
                console.log('http版本不支持该请求')
                break;
            default:
                console.log(`连接错误${err.response.status}`)
        }
    } else {
        console.log('连接到服务器失败')
    }
    return Promise.resolve(err.response)
})


/**
 * 封装get方法
 * @param url
 * @param data
 * @returns {Promise}
 */
export function fetch(url,params={}){
    return new Promise((resolve,reject) => {
        axios.get(url,{
            params:params
        })
            .then(response => {
                resolve(response.data);
            })
            .catch(err => {
                reject(err)
            })
    })
}

/**
 * 封装post请求
 * @param url
 * @param data
 * @returns {Promise}
 */
export function post(url,data = {}){
    return new Promise((resolve,reject) => {
        axios.post(url,data)
            .then(response => {
                resolve(response.data);
            },err => {
                reject(err)
            })
    })
}

最终效果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值