在vue项目中使用高德地图

需求很重要,有需求你才有努力解决问题的方向,加油!

在我们使用vue构建项目的时候,难免在业务需求上会遇到使用高德地图的时候,这时候问题就来了。
我们该怎么在vue项目中插入高德地图?通过度娘我知道了vue-amap这个好东西,详细看官方文档:vue-amap
安装vue-amap
  1. 推荐npm安装

    npm install vue-amap --save
    
  2. 通过CDN引入

    <script src="https://unpkg.com/vue-amap/dist/index.js"><script>
    
引入vue-amap

main.js文件中引入并配置vue-amap

import VueAMap from 'vue-amap';
Vue.use(VueAMap);
VueAMap.initAMapApiLoader({
    key:"你在高德平台申请的key",
    plugin:['AMap.Autocomplete', 'AMap.PlaceSearch', 'AMap.Scale', 'AMap.OverView', 'AMap.ToolBar', 'AMap.MapType', 'AMap.PolyEditor', 'AMap.CircleEditor'],   //插件
    v:"1.4.4"  //版本号,默认高德sdk版本为1.4.4,可自行修改
})

在你的组件中写入如下代码,即可引入地图

<template>
    <div class="map" id="map">
        <el-amap vid="amapDemo" :center="center" :zoom="zoom" class="amap-demo">
        </el-amap>
    </div>
</template>
<style scoped>
    #map{
		width:500px;
		height:500px;
	}
</style>
<script>
    export default{
		data(){
            return{
                zoom:12,
                center: [121.59996, 31.197646],
            }
		}
	}
</script>
对了,差点忘记,在main.js中引入之后如果在函数中输出VueAMap为undefined,这时在main.js中写下:
Vue.prototype.VueAMap = VueAMap;
vue-amap能够抛开高德原生 SDK 覆盖大多数场景,但对于部分定制化程度较高的场景而言,可能还是需要引入高德原生 SDK 来支持。下面介绍如何在 vue-amap 中使用高德 SDK。官方文档
// 在上面代码的基础上加上点东西
// 在el-amap中加上amapManager
<el-amap vid="amapDemo" :amap-manager="amapManager" :center="center" :zoom="zoom" class="amap-demo">
// 然后在script的开头加上
    // npm方式
import { AMapManager } from 'vue-amap';
let amapManager =new AMapManager();
	//CDN方式
let amapManager = new VueAMap.AMapManager();
// 在data中加上
amapManager,

对于大多数 vue-amap 组件,都有 init 这个 event,参数为高德的实例,通过这样暴露高德实例的方式,开发者能够非常自由地将原生 SDK 和 vue-amap 结合起来使用。

这里以 el-amap 组件举例。el-amap 比较特殊,它同时还支持一个 amap-manager 属性,通过这个属性,可以在任何地方拿到高德原生 AMap.Map 实例。

若涉及到高德原生 AMap 需要注意的点:

  • 确保 vue-amap 的导入名不是 AMap,推荐 import VueAMap from 'vue-amap' 避免和高德全局的 AMap 冲突。
  • eslint 报错 AMap is undefined 之类的错误。请将 AMap 配置到 .eslintrcglobals 中。
完整代码:
<template>
    <div class="map" id="map">
        <el-amap vid="amapDemo" :amap-manager="amapManager" :center="center" :zoom="zoom" class="amap-demo">
    </div>
</template>
<style scoped>
    #map{
		width:500px;
		height:500px;
	}
</style>
<script>
	import { AMapManager } from 'vue-amap';
	let amapManager =new AMapManager();
    export default{
		data(){
            return{
                zoom:12,
                center: [121.59996, 31.197646],
                amapManager
            }
		}
	}
</script>
对于vue-amap,发现在实际的开发安装使用的时候还是存在很多问题,对于开发者不太友好。经过度娘的查找,发现有现成的解决方法(因为需求不同,所以根据需求对作者的代码进行了修改)。作者源码:View on GitHub
实现思路:
  1. 创建一个mapDrape的公共组件
  2. 在这个公共组件的created生命周期函数中载入高德地图API
  3. API载入完成即开始地图初始化
  4. 地图API暴露全局变量window.AMap可以直接使用
  5. 监听地图的拖放事件,获得数据后通知自定义事件,对组件外部提供事件接口
  • 首先在src目录下创建config文件夹用于存放地图所需配置,然后在目录中写入config.js

    // 高德地图 key
    export const MapKey = '你在高德地图开发平台申请的key'
    // 地图限定城市
    export const MapCityName = '全国'
    
  • src目录下创建utils文件夹,用于在页面中写入script标签对及其内容,在目录中写入remoteLoad.js

    export default function remoteLoad (url, hasCallback) {
      return createScript(url)
      /**
       * 创建script
       * @param url
       * @returns {Promise}
       */
      function createScript (url) {
        let scriptElement = document.createElement('script')
        document.body.appendChild(scriptElement)
        let promise = new Promise((resolve, reject) => {
          scriptElement.addEventListener('load', e => {
            removeScript(scriptElement)
            if (!hasCallback) {
              resolve(e)
            }
          }, false)
    
          scriptElement.addEventListener('error', e => {
            removeScript(scriptElement)
            reject(e)
          }, false)
    
          if (hasCallback) {
            window.____callback____ = function () {
              resolve()
              window.____callback____ = null
            }
          }
        })
    
        if (hasCallback) {
          url += '&callback=____callback____'
        }
    
        scriptElement.src = url
    
        return promise
      }
    
      /**
       * 移除script标签
       * @param scriptElement script dom
       */
      function removeScript (scriptElement) {
        document.body.removeChild(scriptElement)
      }
    }
    
  • 创建公共组件mapDrap.vue

    载入API的方式类似于jQuery的脚本加载,这里用的别人封装好的一个加载方法

    <template>
      <div class="m-map">
        <div id="js-container" class="map" style="font-size: 0.2rem"></div>
      </div>
    </template>
    
    <script>
    import remoteLoad from '../utils/remoteLoad.js'
    import { MapKey, MapCityName } from '../config/config'
    export default {
      props: ['lat', 'lng'],
      data () {
        return {
          flag:true,
          searchKey: '',
          placeSearch: null,
          dragStatus: false,
          AMapUI: null,
          AMap: null,
          Vdistrict:"",
          district:null,
          polygons:[]
        }
      },
      watch: {
    
      },
      methods: {
        // 实例化地图
        initMap () {
          // 加载PositionPicker,loadUI的路径参数为模块名中 'ui/' 之后的部分
          let AMapUI = this.AMapUI = window.AMapUI;
          let AMap = this.AMap = window.AMap;
          AMapUI.loadUI(['misc/PositionPicker'], PositionPicker => {
            let mapConfig = {
              resizeEnable: true,
              center: [116.30946, 39.937629],
              zoom: 3,
              // cityName: MapCityName
            };
            // if (this.lat && this.lng) {
            //   mapConfig.center = [this.lng, this.lat]
            // }
            let map = new AMap.Map('js-container', mapConfig);
            this.flag = false;
            var Vdistrict = this.$store.state.district.toString();
            var district = null;
            var polygons=[];
            this.$options.methods.drawBounds(map,Vdistrict,district,polygons)
          })
        },
        drawBounds(map,Vdistrict,district,polygons) {
          //加载行政区划插件
          if(!district){
            //实例化DistrictSearch
            var opts = {
              subdistrict: 0,   //获取边界不需要返回下级行政区
              extensions: 'all',  //返回行政区边界坐标组等具体信息
              level: 'district'  //查询行政级别为 市
            };
            district = new AMap.DistrictSearch(opts);
          }
          //行政区查询
          district.search(Vdistrict, function(status, result) {
            map.remove(polygons);   //清除上次结果
            polygons = [];
            var bounds = result.districtList[0].boundaries;
            if (bounds) {
              for (var i = 0, l = bounds.length; i < l; i++) {
                //生成行政区划polygon
                var polygon = new AMap.Polygon({
                  strokeWeight: 1,
                  path: bounds[i],
                  fillOpacity: 0.4,
                  fillColor: '#80d8ff',
                  strokeColor: '#0091ea'
                });
                polygons.push(polygon);
              }
            }
            map.add(polygons);
            map.setFitView(polygons);//视口自适应
          });
        }
      },
      async created () {
        // 已载入高德地图API,则直接初始化地图
        if (window.AMap && window.AMapUI) {
          this.initMap()
        // 未载入高德地图API,则先载入API再初始化
        } else {
          await remoteLoad(`http://webapi.amap.com/maps?v=1.4.13&key=${MapKey}`);
          await remoteLoad('http://webapi.amap.com/ui/1.0/main.js');
          this.initMap()
        }
      }
    }
    </script>
    
    <style lang="css">
    
    </style>
    
  • APP.vue中引入注册这个公共组件,在页面中使用这个组件

    <template>
    	<div class="map" id="map">
        	<mapDrag class="mapbox"></mapDrag>
        </div>
    </template>
    <script>
        import mapDrag from '../../components/mapDrag'
        import urlConfig from '../../assets/js/url.config.js'
        export default {
            components: {
                mapDrag
            },
            data() {
                return {
                    times:'',
                    dateTime:"",
                    datas_one:[],
                    datas_two:[],
                    obj:{},
                    myUrl:"/",
                    cur:0,
                    flag:true,
                    url:urlConfig.Data(),
                    project:{},
                    device:[],
                    projectMessage:{},
                }
            },
            mounted(){
                
            },
    
            methods: {
                
            }
        }
    </script>
    

你可能感兴趣的:(前端,vue,高德地图)