vue3 自定义图标点击放大地图显示子图标移入后显示弹窗

vue yekong

vue 高德地图显示一级数据的图标,鼠标移入一级图标,显示标题,单击一级图标放大地图,双击一级图标显示弹窗。

当一级图标放大后显示二级图标,鼠标移入二级图标后弹出显示信息,地图缩小后二级图标移除。

图标根据状态显示不同的图标

vue3 自定义图标点击放大地图显示子图标移入后显示弹窗

演示地址

vue3 自定义图标点击放大地图显示子图标移入后显示弹窗

首先引入高德地图

在vue项目中的index.html中引入高德地图,这里的key需要自己申请。

<script
        type="text/javascript"
        src="https://webapi.amap.com/maps?v=1.4.15&key=your key&plugin=AMap.Geocoder,AMap.RangingTool,AMap.Heatmap"
></script>
<script src="//webapi.amap.com/ui/1.0/main.js?v=1.0.11"></script>

html

使用div用来渲染高德地图

<template>
  <div class="maps">
    <div ref="allmap" class="mapsMain"></div>
  </div>
</template>

高德地图

这里的地图使用的是卫星图,通过路网new AMap.TileLayer.RoadNet()来让地图上显示地名等信息。

首先准备数据,因为有两种类型的弹窗,为了避免冲突所以我们创建两个方法来处理这两种图标。

一级图标逻辑处理

1.鼠标移入显示标题,我们通过创建给AMap.Marker添加title来实现
2.单击放大地图,我们给图标绑定单击事件双击后,触发单大地图的方法。
3.双击显示详细信息,当双击图标后,我们需要显示一个弹窗来显示详细信息。

二级图标逻辑处理

鼠标移入二级图标后弹窗显示详细信息,鼠标移开后关闭弹窗

当地图缩小后,图标移除。

实例代码

    // 创建一级图标
    createMarker(location, iconSrc, type, baseName = '') {
      var that = this;
      // 创建 marker
      const marker = new AMap.Marker({
        position: location.coordinates,
        icon: new AMap.Icon({
          size: new AMap.Size(38, 43),
          image: location.icon,
          imageSize: new AMap.Size(38, 43)
        }),
        offset: new AMap.Pixel(-19, -21.5),
        title: type === 'jidilist' ? baseName : '' // 仅在类型为基地时设置标题
      });

      // 根据类型定制弹窗内容
      let title = '';
      let icon = '';
      let infoClass = '';
      let statusHTML = ''; // 状态信息的HTML字符串
      let bodyHTML = ''; // 状态信息的HTML字符串

      switch (type) {
        case 'jidilist':
          title = '基地信息';
          icon = icon_jidi2;
          infoClass = 'jidilist';
          bodyHTML = `<div class="bodyInfo2">
<div class="bodyInfo2l">
<img src="${img}" alt="">
</div>
<div class="bodyInfo2r">
                        <div class="bodyInfoItem2">
                        <img src="${dot}" alt="">
                        <span>基地名称:<em>${location.baseName}</em></span>
                        </div>
                        <div class="bodyInfoItem2">
                        <img src="${dot}" alt="">
                        <span>位置:<em>${location.address}</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>经纬度:<em>49°15′</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>场景:<em>${location.scene}</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>海拔:<em>29.354002</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>种植面积:<em>${location.demonstrationArea}亩</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>种植作物:<em>${location.specificCrop}</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>联系人:<em>${location.contactPerson}</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>联系电话:<em>${location.contactPhone}</em></span>
                        </div>
                        </div>
</div>`
          break;
      }

      const infoWindow = new AMap.InfoWindow({
        isCustom: true, // 使用自定义窗口
        content: document.createElement('div'), // 创建一个div元素用于内容填充
        offset: new AMap.Pixel(0, -40)
      });

      // 设置内容
      const content = document.createElement('div');
      content.className = 'gdPopWin' + ' ' + infoClass
      content.innerHTML = `
    <div class="gdPopWinInner">
      <div class="gdPopWinInnerTop">
        <div class="gdPopWinInnerTopLeft">
          <img src="${icon}" alt="icon" class="gdPopWinIcon" />
          <span class="gdPopWinTitle">${title}</span>
          ${statusHTML}  <!-- 这里插入状态 -->
        </div>
        <div class="gdPopWinInnerTopRight">
          <img src="${close}" alt="close" class="gdPopWinClose" />
        </div>
      </div>
      <!-- 这里可以根据需要添加更多的信息 -->
       ${bodyHTML}
    </div>
  `;

      // 找到关闭按钮,并为其添加点击事件监听器
      const closeButton = content.querySelector('.gdPopWinClose');
      closeButton.addEventListener('click', function () {
        infoWindow.close();
      });

      // 更新信息窗口内容
      infoWindow.setContent(content);

      // marker 点击时显示信息窗口
      marker.on('dblclick', function () {
        infoWindow.open(that.map, marker.getPosition());
      });

      // // 修改marker的点击事件
      if (type === 'jidilist') {
        marker.on('click', function () {
          // 放大并且居中到该基地
          that.map.setZoomAndCenter(15, location.coordinates);
          // // 渲染该基地下的车辆和地块
          console.log(location.dikuaiList)
          location.dikuaiList.forEach((dikuai) => {
            that.createMarker2(dikuai, icon_dikuai, 'dikuaiList', location);
          });
          location.carList.forEach((car) => {
            const icon = car.onLine === '在线' ? icon_cheliang : icon_cheliang_lixian;
            that.createMarker2(car, icon, 'carList', location);
          });
        });
      }
      // 添加 marker 到地图
      that.map.add(marker);
    },
    // 创建二级图标
    createMarker2(location, iconSrc, type, data) {
      var that = this;
      // 创建 marker
      const marker = new AMap.Marker({
        position: location.coordinates,
        icon: new AMap.Icon({
          size: new AMap.Size(38, 43),
          image: iconSrc,
          imageSize: new AMap.Size(38, 43)
        }),
        offset: new AMap.Pixel(-19, -21.5),
      });
      that.marker2Array.push(marker);
      // 根据类型定制弹窗内容
      let title = '';
      let icon = '';
      let infoClass = '';
      let statusHTML = ''; // 状态信息的HTML字符串
      let bodyHTML = ''; // 状态信息的HTML字符串

      switch (type) {
        case 'dikuaiList':
          title = '地块信息';
          icon = icon_dikuai2;
          infoClass = 'dikuaiList';
          bodyHTML = `<div class="bodyInfo">
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>作物品种:<em>${data.specificCrop}</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>经纬度:<em>49°15′</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>种植面积:<em>${data.demonstrationArea}亩</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>海拔:<em>29.354002</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>土壤类型:<em>沙土</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>坡度:<em>${data.scene}</em></span>
                        </div>
                        <div class="bodyInfoItem2">
                        <img src="${dot}" alt="">
                        <span>所属基地:<em>${data.baseName}</em></span>
                        </div>
                        <div class="bodyInfoItem2">
                        <img src="${dot}" alt="">
                        <span>位置:<em>${data.address}</em></span>
                        </div>
                        </div>`
          break;
        case 'carList':
          title = '车辆信息';
          icon = icon_cheliang2;
          infoClass = location.onLine === '在线' ? 'carlist-online' : 'carlist-offline';
          // 根据在线状态动态添加status
          console.log(location.onLine)
          console.log(1111)
          statusHTML = location.onLine === '在线' ?
              '<span class="status" style="color: green;">在线</span>' :
              '<span class="status2" style="color: grey;">离线</span>';
          bodyHTML = `<div class="bodyInfo">
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>车辆类型:<em>耕种机</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>当日作业面积:<em>102亩</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>编号:<em>Y-7-S0208</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>电话:<em>${data.contactPhone}</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>驾驶员:<em>${data.contactPerson}</em></span>
                        </div>
                        <div class="bodyInfoItem">
                        <img src="${dot}" alt="">
                        <span>无故障作业时间:<em>42分</em></span>
                        </div>
                        <div class="bodyInfoItem2">
                        <img src="${dot}" alt="">
                        <span>所属基地:<em>${data.baseName}</em></span>
                        </div>
                        <div class="bodyInfoItem2">
                        <img src="${dot}" alt="">
                        <span>当前位置:<em>${data.address}</em></span>
                        </div>
                        </div>
`
          break;
      }

      const infoWindow = new AMap.InfoWindow({
        isCustom: true, // 使用自定义窗口
        content: document.createElement('div'), // 创建一个div元素用于内容填充
        offset: new AMap.Pixel(0, -40)
      });

      // 设置内容
      const content = document.createElement('div');
      content.className = 'gdPopWin' + ' ' + infoClass
      content.innerHTML = `
    <div class="gdPopWinInner">
      <div class="gdPopWinInnerTop">
        <div class="gdPopWinInnerTopLeft">
          <img src="${icon}" alt="icon" class="gdPopWinIcon" />
          <span class="gdPopWinTitle">${title}</span>
          ${statusHTML}  <!-- 这里插入状态 -->
        </div>
        <div class="gdPopWinInnerTopRight">
          <img src="${close}" alt="close" class="gdPopWinClose" />
        </div>
      </div>
      <!-- 这里可以根据需要添加更多的信息 -->
       ${bodyHTML}
    </div>
  `;

      // 找到关闭按钮,并为其添加点击事件监听器
      const closeButton = content.querySelector('.gdPopWinClose');
      closeButton.addEventListener('click', function () {
        infoWindow.close();
      });

      // 更新信息窗口内容
      infoWindow.setContent(content);

      // marker 点击时显示信息窗口
      marker.on('mouseover', function () {
        infoWindow.open(that.map, marker.getPosition());
      });

      // 添加 mouseout 事件监听器
      marker.on('mouseout', function () {
        infoWindow.close();
      });


      // 添加 marker 到地图
      that.map.add(marker);
    },

    // 高德地图相关
    getGdMap() {
      var that = this;
      that.map = new AMap.Map(this.$refs.allmap, {
        scrollWheel: true,
        viewMode: '2D',
        resizeEnable: true,
        layers: [ //使用多个图层
          new AMap.TileLayer.Satellite(), //使用卫星图
          // 路网
          new AMap.TileLayer.RoadNet()
        ],
        zoom: 4,
        maxZoom: 30,
        minZoom: 0,
        center: [106.413099, 34.952327],
      });
// 渲染基地列表,不立即渲染车辆和地块
      this.jidilist.forEach((location) => {
        this.createMarker(location, icon_jidi, 'jidilist', location.baseName);
      });


      // 地图zoom变化事件监听器
      this.map.on('zoomend', function() {
        var zoom = that.map.getZoom(); // 获取当前地图的zoom等级
        if (zoom < 10) {
          // 如果zoom等级小于10,移除所有createMarker2创建的markers
          that.marker2Array.forEach(function(marker) {
            that.map.remove(marker);
          });
          // 清空存储的marker2的markers数组
          that.marker2Array = [];
        }
      });
    },

到这里vue vue3 自定义图标点击放大地图显示子图标移入后显示弹窗效果就完成了。

更多高德地图实例

vue 高德地图效果实例汇总

实例代码下载

项目基于vue3 vite js node.js 16 开发

相关文件下载地址
此资源需支付 ¥2 后下载
支付宝购买扫右侧红包码购买更优惠,如无法下载请联系微信:17331886870
喜欢
vue3 自定义图标点击放大地图显示子图标移入后显示弹窗