@vuemap/vue-amap高德vue组件库常用技巧(一)

1,921 阅读3分钟

我正在参加「掘金·启航计划」

@vuemap/vue-amap是基于高德JSAPI2.0、Loca2.0封装的vue组件库,支持vue2、vue3版本。首页地址:vue-amap.guyixi.cn/

在使用组件库进行地图开发时,常常根据需求需要做一些特殊的功能开发,今天主要介绍一些日常开发中常用的开发功能技巧。

1、JSAPI懒加载降低页面白屏时间

在使用组件库时我们需要保证先加载高德JSAPI,因此正常使用时我们会直接在main.js文件中直接加载JSAPI,示例如下:

initAMapApiLoader({
  key: 'YOUR_KEY',
  securityJsCode: 'securityJsCode', // 高德key需要配合安全密钥使用
  //Loca:{
  //  version: '2.0.0'
  //} // 如果需要使用loca组件库,需要加载Loca
})

在不考虑首屏加载性能时该方案可以快速加载API,但需要优化首屏加载时需要调整加载时机。 创建一个map.js文件,文件内容如下:

import {initAMapApiLoader} from "@vuemap/vue-amap";

export function initMapApi() {
  initAMapApiLoader({
    key: 'YOUR_KEY',
    securityJsCode: 'securityJsCode',
    version: '2.0',
  })
}

在地图使用的vue文件中执行地图API加载,需要确保加载代码写在组件的beforeMount生命周期中,示例如下:

<template>
  <div style="height: 500px">
    <el-amap />
  </div>
</template>
<script setup>
import {onBeforeMount} from "vue";
import {initMapApi} from "@/utils/map";
onBeforeMount(() => {
  initMapApi()
})
</script>

2、地图选点

使用地图一个常见的功能就是地图选点,通过点击地图生成一个marker并可以通过拖拽标记来实现地图选点,更可以配合地图的地理逆解析能力获取当前点位的位置信息。代码示例如下:

<template>
  <div style="height: 500px;">
    <el-amap @init="initMap" @click="clickMap">
      <el-amap-marker v-if="markerCenter" v-model:position="markerCenter" anchor="bottom-center" :draggable="true" @dragend="dragMarker"></el-amap-marker>
    </el-amap>
  </div>
  <div>
    <button @click="selectPoint">地图选点</button>
    <span style="margin: 0 20px;">地址:</span>
    <span>{{address}}</span>
  </div>
</template>
<script setup>

import { ref, onBeforeMount } from "vue";
import {initMapApi} from "@/utils/map";

onBeforeMount(() => {
  initMapApi()
})

let geocoder = null

const markerCenter = ref()

const address = ref('')

let canSelect = false
const selectPoint = () => {
  canSelect = true
  markerCenter.value = null
}

const initMap = (map) => {
  AMap.plugin('AMap.Geocoder', () => {
    geocoder = new AMap.Geocoder({
    })
  })
}

const clickMap = (e) => {
  if(!canSelect){
    return
  }
  markerCenter.value = [e.lnglat.lng, e.lnglat.lat]
  canSelect = false
  convertLocation()
  console.log('click map: ', e)
}

const convertLocation = () => {
  if(geocoder){
    geocoder.getAddress(markerCenter.value, (status, result) => {
      if (status === 'complete' && result.info === 'OK') {
        console.log('result: ', result)
        address.value = result.regeocode.formattedAddress
      }
    })
  }
}

const dragMarker = () => {
  convertLocation()
}

</script>

<style>
</style>

效果图如下:

3、使用当前位置初始化地图

日常使用时我们都是会给地图提供一个默认的中心点,但有些时候我们需要在用户打开地图时将中心点直接定位到用户当前位置,这时候就需要使用地图的定位组件。由于某些原因在使用chrome时定位会失败。代码示例如下:

<template>
  <div style="height: 500px;">
    <el-amap @init="initMap">
      <el-amap-control-geolocation @init="initLocation"></el-amap-control-geolocation>
    </el-amap>
  </div>
</template>
<script setup>
import { onBeforeMount } from "vue";
import {initMapApi} from "@/utils/map";

onBeforeMount(() => {
  initMapApi()
})

let mapInstance = null
const initMap = (map) => {
  mapInstance = map
}
const initLocation = (location) => {
  location.getCurrentPosition((status, result) => {
    console.log('定位信息:', result);
    if(status === 'complete' && result.info === 'SUCCESS'){
      mapInstance.setCenter([result.position.lng, result.position.lat])
    }else{
      console.log('定位失败: ', result.message )
    }
  })
}
</script>

<style>
</style>

效果图如下:

4、电子围栏

绘制电子围栏是地图开发过程中常见的功能,利用mouse-tool组件以及其他矢量图形组件可以快捷的实现电子围栏,目前矢量图形的关键字段都已实现v-model能力,因此在编辑完图形后可以简单便捷的获取到编辑后的对象,代码如下:

<template>
  <div style="height: 500px;">
    <el-amap>
      <el-amap-mouse-tool ref="mouseToolRef" :type="type" @draw="drawVector"></el-amap-mouse-tool>
      <el-amap-circle v-if="type === 'circle' && edit" v-model:center="circleData.center" v-model:radius="circleData.radius" :editable="true"></el-amap-circle>
      <el-amap-rectangle v-if="type === 'rectangle' && edit" v-model:bounds="rectangleData" :editable="true"></el-amap-rectangle>
      <el-amap-polygon v-if="type === 'polygon' && edit" v-model:path="polygonData" :editable="true"></el-amap-polygon>
    </el-amap>
  </div>
  <div>
    <button @click="draw('circle')">绘制圆</button>
    <button @click="draw('rectangle')">绘制矩形</button>
    <button @click="draw('polygon')">绘制多边形</button>
  </div>
</template>
<script setup>
import { onBeforeMount, reactive, ref } from "vue";
import {initMapApi} from "@/utils/map";

onBeforeMount(() => {
  initMapApi()
})
const mouseToolRef = ref()
const type = ref('circle')
const edit = ref(false)
const circleData = reactive({
  center: [0,0],
  radius: 0
})
const rectangleData = ref([])
const polygonData = ref([])
const drawVector = (data) => {
  console.log('drawVector: ', data)
  if(type.value === 'circle'){
    circleData.center = data.center;
    circleData.radius = data.radius;
  }else if(type.value === 'rectangle'){
    rectangleData.value = data
  }else if(type.value === 'polygon'){
    polygonData.value = data
  }
  mouseToolRef.value?.$$close()
  edit.value = true
}

const draw = (typeName) => {
  type.value = typeName;
  edit.value = false;
  mouseToolRef.value?.$$open()
}
</script>

<style>
</style>

示例如下: