Vue3引入高德地图基本操作一条龙~很详细~看了你也会!

你们好,我是金金金。

image.png

前言

撰写本文的初衷既是为了方便各位读者,也是为了自我提升。在未来面对一些基本操作时,我们不再需要频繁查阅官方文档,节省宝贵的时间。网络上的相关资料虽然丰富,但质量良莠不齐,查找起来颇为不便。因此,我希望通过这篇整理详尽、条理清晰的文章,为大家提供一个可靠的信息来源

看完本篇文章能学到什么?

如何把高德地图引入至Vue3项目中;

地图正常展示;

根据经纬度打点标记、自定义图标;

点标记覆盖物如何触发点击事件;

点击点标记覆盖物打开自定义信息窗体展示;

点聚合;

点聚合点击判断的一个方式;

实操

引入高德地图至Vue3项目中以及地图的一个正常展示

  1. 成为开发者并创建 key(为了正常调用 API ,需先注册成为高德开放平台开发者,并申请 web 平台(JS API)的 key 和安全密钥)
    • 这里不过多赘述,自己去申请注册一下,点击可跳往操作地址
    • 提示:在2021年12月02日以后申请的key需要配合安全密钥一起使用。
  2. NPM 安装 Loader
    npm i @amap/amap-jsapi-loader --save
    
  3. 新建一个组件,我这里名为MapContainer.vue,用作地图组件(名字随意)
  4. 创建地图容器
    • MapContainer.vue 地图组件中创建 div 标签作为地图容器 ,并设置地图容器的 id 属性为 container
    <template> 
        <div id="container"></div> 
    </template>
    
  5. 设置地图样式
    <style scoped>
    #container {
      width: 100%;
      height: 100%;
    }
    </style>
    
  6. 初始化地图
    onMounted(() => {
     window._AMapSecurityConfig = {
       securityJsCode: "「你申请的安全密钥」",
     };
     AMapLoader.load({
       key: "", // 申请好的Web端开发者Key,首次调用 load 时必填
       version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
       plugins: ["AMap.Scale"], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
     })
       .then((AMap) => {
         map = new AMap.Map("container", {
           // 设置地图容器id
           viewMode: "3D", // 是否为3D地图模式
           zoom: 11, // 初始化地图级别
           center: [116.397428, 39.90923], // 初始化地图中心点位置
         });
       })
       .catch((e) => {
         console.log(e);
       });
    })
    

好了,大概的步骤就是这么多,所有代码如下

在这里插入图片描述

测试

在这里插入图片描述

根据经纬度打点标记、自定义图标

分为三步走

  1. 创建Marker对象
  2. 自定义Icon传入至Marker
  3. Marker添加到地图上

在这里插入图片描述

添加多个点标记也很简单,传入多个经纬度数组数据,循环创建Marker添加即可

测试

在这里插入图片描述

点标记覆盖物如何触发点击事件

  • 比较简单,使用marker对象.on方法就可以监听到点击事件
marker.on('click', function (e) {
  alert("我被点击了")
})

在这里插入图片描述

测试

在这里插入图片描述

点击点标记覆盖物打开自定义信息窗体展示

注意:一个地图实例每次只能打开一个信息窗体

  • 先看一下默认信息窗体如何展示

默认信息窗体

  • 默认信息窗体已有关闭按钮,只需要设定InfoWindowcontent属性。content是字符串拼接的 DOM 元素,content的样式可以自定义。

很简单,也可以分三步走

  1. 编写信息窗体的内容
  2. 创建 infoWindow 实例,传入信息窗体内容
  3. 打开显示信息窗体
// 信息窗体的内容
const content = [
  "<div><b>高德软件有限公司</b>",
  "电话 : 010-84107000   邮编 : 100102",
  "地址 : 北京市望京阜通东大街方恒国际中心A座16层</div>",
]
// 创建 infoWindow 实例
const infoWindow = new AMap.InfoWindow({
  content: content.join("<br>"), // 传入字符串拼接的 DOM 元素
  anchor: "top-left", // 指定自定义锚点位置
})
// 打开信息窗体
infoWindow.open(map, map.getCenter()); // map 为当前地图的实例,map.getCenter() 用于获取地图中心点坐标。

信息窗体通常是和点击事件配合使用的,例如:点击了某个覆盖物弹出相关信息

  1. 当覆盖物被点击时,调用打开信息窗体的方法

    在这里插入图片描述

  2. 信息窗体代码如下

    在这里插入图片描述

测试

在这里插入图片描述

自定义信息窗体

有些时候默认的信息窗体是不能满足业务需求的,比如框和关闭的icon都要改动,那就需要完全自定义信息窗体了

要自定义信息窗体,只需把 InfoWindowisCustom 属性设置为 true ,信息窗体就会变成自定义信息窗体。与默认信息窗体的不同在于,自定义信息窗体需要自己通过 content 来实现关闭按钮以及全部外观样式,同时需要通过 offset 指定锚点位置,offset 为相对于 content 下边缘中间点的位移

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这里的重点其实就是css的编写了,因为使用了自定义信息窗体,框的样式都需要自己编写。

测试

在这里插入图片描述

自定义信息窗体事件触发

  1. 通过onclick绑定了事件

在这里插入图片描述

  1. 定义相对应的方法

在这里插入图片描述

  1. 需要挂载到window全局上,不然会报错函数未定义

在这里插入图片描述

测试
  • 点击手环详情以及关闭自定义信息窗体都是没有任何问题的

在这里插入图片描述

点聚合

有两种方式,分别为:按距离聚合和按索引聚合。我这里采用的是按距离聚合

大致步骤可以分为三步走

  1. 创建聚合点数据
  2. 自定义图标样式
  3. 添加聚合组件
// 点聚合数据
const _renderMarker = (context) => {
    // context 为回调参数,
    // 包含如下属性 marker:当前非聚合点
    context.marker.setContent(`<img src="${CourtDIcon}" alt="" />`)
}
const points = [
    { weight: 8, lnglat: ['120.475655', '27.570581'] },
    { weight: 1, lnglat: ['120.472792', '27.564668'] },
    { weight: 1, lnglat: ['120.551636', '27.66167'] },
    { weight: 1, lnglat: ['120.546932', '27.773796'] },
    { weight: 1, lnglat: ['120.341914', '27.644967'] },
]
// 点聚合
new AMap.MarkerCluster(map, points, {
    gridSize: 60, //数据聚合计算时网格的像素大小
    renderMarker: _renderMarker, //上述步骤的自定义非聚合点样式
})

在这里插入图片描述

点聚合点击判断

其实也很简单,思路:通过包含点的数量判断是否是聚合点,数量为1说明不是聚合点

一些参考的代码我贴出来供大家参考~

在这里插入图片描述

全部代码

<script setup>
  import { onMounted, onUnmounted, ref } from 'vue'
  import AMapLoader from '@amap/amap-jsapi-loader'
  import WristbandIcon from '@/assets/imgs/device/ding_wei.png'
  import UserIcon from '@/assets/imgs/user.png'
  import ServiceIcon from '@/assets/imgs/service.png'
  import CourtDIcon from '@/assets/imgs/court_d.png'

  let map = null
  const infoWindow = ref(null)

  const closeInfo = () => {
    infoWindow.value?.close()
  }
  const handleWristbandClick = () => {
    alert("点击了手环")
  }
  const _renderMarker = (context) => {
    // context 为回调参数,
    // 包含如下属性 marker:当前非聚合点
    context.marker.setContent(`<img src="${CourtDIcon}" alt="" />`)
  }
  
  const openInfo = () => {
    // 构建信息窗体中显示的内容
    const info = []

    info.push('<div class="info-box">')
    // 主题内容部分
    info.push('<div class="info-box-main">')
    info.push(`<img class="info-box-main-img" src="${UserIcon}" alt="" />`)
    info.push('<div>')
    info.push(`<p>姓名: 张三</p>`)
    info.push(`<p>电话: 18888888888</p>`)
    info.push('</div>')
    info.push('</div>')
    // 手环
    info.push('<div class="info-box-footer">')
    info.push(`<img class="info-box-footer-img" src="${ServiceIcon}" alt="" />`)
    info.push('<span οnclick="handleWristbandClick()">手环详情</span>')
    info.push('<span>></span>')
    info.push('</div>')
    info.push('</div>')
    // 三角
    info.push('<div class="info-triangle">')
    info.push('</div>')
    // 关闭按钮
    info.push('<div class="info-close" οnclick="closeInfo()">×')
    info.push('</div>')
    
    // 创建 infoWindow 实例
    infoWindow.value = new AMap.InfoWindow({
      isCustom: true, //使用自定义窗体
      content: info.join('<br>'), //传入字符串拼接的 DOM 元素
      anchor: 'top-left', // 指定自定义锚点位置
    })
    // 打开信息窗体
    infoWindow.value.open(map, map.getCenter()) //map 为当前地图的实例,map.getCenter() 用于获取地图中心点坐标。
  }
  onMounted(() => {
    window._AMapSecurityConfig = {
      securityJsCode: '这里填写你的密钥',
    }
    AMapLoader.load({
      key: '这里写你申请的key', // 申请好的Web端开发者Key,首次调用 load 时必填
      version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
      plugins: ['AMap.Scale'], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
    })
      .then((AMap) => {
        map = new AMap.Map('container', {
          // 设置地图容器id
          viewMode: '3D', // 是否为3D地图模式
          zoom: 11, // 初始化地图级别
          center: [116.397428, 39.90923], // 初始化地图中心点位置
        })
        // 创建一个 icon
        const wristbandIcon = new AMap.Icon({
          image: WristbandIcon,
        })
        // 创建一个 marker
        const marker = new AMap.Marker({
          position: new AMap.LngLat(116.397428, 39.90923), // 根据经纬度设置 maker 位置
          icon: wristbandIcon, // 设置图标
          offset: new AMap.Pixel(-13, -30) // 设置图标偏移量
        })
        // 覆盖物点击事件
        marker.on('click', function (e) {
          openInfo()
        })
        // 将 marker 添加到地图
        map.add([marker])
        
        // 点聚合数据
        const points = [
          { weight: 8, lnglat: ['120.475655', '27.570581'] },
          { weight: 1, lnglat: ['120.472792', '27.564668'] },
          { weight: 1, lnglat: ['120.551636', '27.66167'] },
          { weight: 1, lnglat: ['120.546932', '27.773796'] },
          { weight: 1, lnglat: ['120.341914', '27.644967'] },
        ]
        // 点聚合
        new AMap.MarkerCluster(map, points, {
          gridSize: 60, //数据聚合计算时网格的像素大小
          renderMarker: _renderMarker, //上述步骤的自定义非聚合点样式
        })

        window.closeInfo = closeInfo
        window.handleWristbandClick = handleWristbandClick
      })
      .catch((e) => {
        console.log(e)
      })
  })
  onUnmounted(() => {
    map?.destroy()
  })
</script>

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

<style lang="scss">
  #container {
    width: 100%;
    height: 100%;
  }
  .info-box {
    padding: vw(15);
    color: #fff;
    background-color: #01161ccc;
    box-shadow: inset vw(-2) 0 vw(8) vw(2) #428ffccc, 0 0 vw(6) vw(2) #00000088;
    border: vw(2) solid rgb(86, 156, 255);
    border-radius: vw(10);
    &-main {
      display: flex;
      align-items: center;
      font-size: vh(16);
      &-img {
        width: vw(40);
        height: vw(40);
        margin-right: vw(10);
      }
    }
    &-footer {
      margin-top: vh(10);
      font-size: vh(14);
      color: #00e5ff;
      display: flex;
      align-items: center;
      &-img {
        width: vw(14);
        height: vw(14);
        margin-right: vw(3);
      }
    }
  }
  .info-triangle {
    width: 0;
    height: 0;
    border-left: vw(8) solid transparent;
    border-right: vw(8) solid transparent;
    border-top: vw(8) solid #008fd4;
    margin: 0 auto;
  }
  .info-close {
    position: absolute;
    right: vw(-8);
    top: vw(-8);
    width: vw(20);
    height: vw(20);
    background-color: #0ec1d4;
    color: #fff;
    border-radius: 50%;
    font-weight: bold;
    display: flex;
    justify-content: center;
    align-items: center;
  }
</style>
 
        
  • 编写有误还请大佬指正,万分感谢。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值