vue3 运用高德地图 自定义弹框 为信息窗体 添加 new AMaps.value.InfoWindow 添加事件

发布于:2024-06-21 ⋅ 阅读:(70) ⋅ 点赞:(0)

效果图
在这里插入图片描述
划过散点的时候出现每个三点位置的数据提示
在这里插入图片描述
点击具体散点获取展示信息弹框,并为其添加点击事件
在这里插入图片描述
注意点:
1 即使是用的vue,也不能使用@click为窗体添加点击事件,需要使用onclick,
(原因:这是因为你的弹窗内容是以字符串的形式插入到 DOM 中的。此时你给它添加的点击事件不会被 Vue 的事件监听系统所识别和处理,因为这是在 Vue 的作用范围之外的。但是,如果你把这个函数挂载到 window 对象上,那么无论在哪个地方调用这个函数,浏览器都能找到并且执行它)。

2 并且在定义了函数后,使用该函数还是会报函数未定义的错误,需要在window下添加该函数,点击时可以在原型链中找到该函数。
3 设置信息窗体,并为信息窗体里的函数添加点击事件。
处理过程:
1 给每一个 infowindow 加上一个类名,然后进行绑定事件,
2 高德地图 infowindow 不会马上就渲染出来,只有点击 marker 之后才会生成
3 所以需要在生成 infowindow 后才能绑定事件

在这里插入图片描述
在这里插入图片描述

代码实现

<template>
  <div>
    <div class="top-box">
      <Title title="煤矿地理分布图" />
      <seachIpt @clickSearch="clickSearch" />
    </div>
    <div class="map-box" v-loading="loading">
      <div class="icon">
        <span @click="postMine('container')" class="left-back">返回主地图</span>
        <span class="iconfont icon-a-zujian28421" @click="handleFullScreen"></span>
      </div>
      <div ref="chinaMap" id="container" class="map-content"></div>
      <leftMark />
    </div>
  </div>
  <mapDialog v-model:value="show" />
</template>

<script lang="ts" setup>
import AMapLoader from '@amap/amap-jsapi-loader'
import LabelsData from './china'
import Title from '../title.vue'
import leftMark from './left-mark.vue'
import seachIpt from './seachIpt.vue'
import { ElMessage } from 'element-plus'
import { postMineInfo } from '@/api/dashboard/index'
import mapDialog from './mapDialog.vue'
import { useRouter } from 'vue-router'
let show = ref(false)
let infoWindow = ref(null)
const handleFullScreen = () => {
  infoWindow.value?.close()
  show.value = true
}

//搜索
const clickSearch = (v: string) => {
  getMineInfo(v)
}

//获取该煤矿信息
let dataList = ref([])
const getMineInfo = (v: string) => {
  infoWindow.value = null
  postMineInfo({ mineName: v, region: 1 })
    .then((res: any) => {
      const { data, success } = res
      if (success) {
        if (data?.length > 0) {
          //构建信息窗体中显示的内容
          dataList.value = data[0]
          var info = []
          info.push(`<div style='font-size: 16px;'>
            <div style=' display: flex;align-items: center;justify-content: space-between;margin-bottom:8px ;padding-bottom:4px; border-bottom: 1px solid #eeeeee;'>
              <el-tooltip class="box-item" effect="dark" :content="${
                data[0].mineName
              }" placement="top">
                <span class="left-title" style="color: #3076fe; cursor: pointer;" data-id="moreIds" onclick="more(event)">
                  ${data[0].mineName}
                </span>
              </el-tooltip>
            </div>
            <div class="content">
              <div style='display: flex;line-height: 30px;'>
                <span style='text-align: right;width: 129px;color: #707070;'>所属片区: </span>
                <span style='width: 206px;color: #262626;'>${
                  data[0].zmjArea || '--'
                }</span>
              </div>
              <div style='display: flex;line-height: 30px;'>
                <span style='text-align: right;width: 129px;color: #707070;'>煤矿位置: </span>
                <span style='width: 206px;color: #262626;'>${
                  data[0].province ||
                  data[0].city ||
                  data[0].region ||
                  data[0].orgAddress
                    ? (data[0].province ? data[0].province : '') +
                      (data[0].city ? data[0].city : '') +
                      (data[0].region ? data[0].region : '') +
                      (data[0].orgAddress ? data[0].orgAddress : '')
                    : '--'
                }</span>
              </div>
              <div style='display: flex;line-height: 30px;'>
                <span style='text-align: right;width: 129px;color: #707070;'>煤矿性质: </span>
                <span style='width: 206px;color: #262626;'>${
                  data[0].mineProperty || '--'
                }</span>
              </div>
              <div style='display: flex;line-height: 30px;'>
                <span style='text-align: right;width: 129px;color: #707070;'>核定生产能力: </span>
                <span style='width: 206px;color: #262626;'>${
                  data[0].actualProductCapacity || '--'
                }${data[0].actualProductCapacity ? '万吨' : ''}</span>
              </div>
              <div style='display: flex;line-height: 30px;'>
                <span style='text-align: right;width: 129px;color: #707070;'>是否ZMJ客户: </span>
                <span style='width: 206px;color: #262626;'>${
                  data[0].customer === 1 ? '是' : '否'
                }</span>
              </div>
            </div>
          </div>`)
          infoWindow.value = new AMaps.value.InfoWindow({
            anchor: 'top-left',
            content: info.join('') //使用默认信息窗体框样式,显示信息内容
          })
          let amplify = ref(0)
          if (data[0].zmjArea !== '国际') {
            amplify.value = 10
          } else {
            amplify.value = 5
          }
          infoWindow.value.open(map.value, [data[0].longitude, data[0].latitude])
          map.value.setZoomAndCenter(amplify.value, [data[0].longitude, data[0].latitude])
        } else ElMessage.error('暂未查到该煤矿信息')
      } else {
        ElMessage.error(res.message)
      }
    })
    .catch((err) => {
      console.log(err)
    })
}

const chinaMap = ref()
let AMaps = ref(null)
let map = ref(null)

let normalMarker = ref(null)
let labelsLayer = ref(null)
let markers = ref([])
const imgList = ref([
  new URL(`@/assets/home/blue-mark.png`, import.meta.url).href,
  new URL(`@/assets/home/green-mark.png`, import.meta.url).href
])

onActivated(() => {
  postMine('container')
})

const router = useRouter()
const toMineDetails = (val:any ) => {
  router.push({
    name: 'mineBasicInfoDetail',
    params: { model: val?.mineName },
    query: { id: val?.mineId, projectName: val?.mineName }
  })
}

let loading = ref(false)
//获取煤矿地理坐标
const postMine = (dom: any) => {
  loading.value = true
  postMineInfo({ region: 1 })
    .then((res: any) => {
      const { data, success } = res
      if (success) {
        initMap(data, dom)
      } else {
        initMap([], dom)
      }
    })
    .catch(() => {
      initMap([], dom)
    })
    .finally(() => {
      loading.value = false
    })
}
//初始化地图加载
const initMap = (data: any, dom: any) => {
  const AMapLoad = ref<any>(AMapLoader)
  // map.value && map.value.destroy()
  AMapLoad.value
    .load({
      key: '337c7e7dda33e11839f80aa219f2fc8a', // 申请好的Web端开发者Key,首次调用 load 时必填
      // version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
      plugins: [
        'AMap.DistrictSearch',
        'AMap.DistrictLayer',
        'AMap.Map',
        'AMap.Polygon',
        'AMap.LabelsLayer',
        'AMap.LabelMarker',
        'AMap.Marker'
      ], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
      AMapUI: {
        //重点就是这个
        version: '1.0',
        plugins: ['misc/PathSimplifier', 'overlay/SimpleMarker'] //SimpleMarker设置自定义图标,PathSimplifier轨迹展示组件
      }
    })
    .then((AMap: any) => {
      AMaps.value = AMap
      map.value = new AMap.Map(dom, {
        layers: [
          // disWorld,
        ],
        // resizeEnable: true,
        viewMode: '3D',
        zIndex: 5,
        zoom: 3,
        zoomEnable: true, //地图是否可缩放
        dragEnable: true, // 地图是否可通过鼠标拖拽平移
        rotateEnable: false, // 地图是否可旋转
        // mapStyle: 'amap://styles/10f9d1d306dec0990c6048597ab3bfcb',
        zooms: [4.3, 20], // 缩放级别范围
        center: [105.602725, 37.076636],
        defaultCursor: 'pointer', // 地图默认鼠标样式
        showLabel: true, // 是否展示地图文字和 POI 信息。
        showIndoorMap: false, // 是否自动展示室内地图,默认是 false
        features: ['bg', 'building', 'road', 'point']
      })
      const _window = window as any
      nextTick(()=>{
        _window.more = (event:any) => {
          const e = event.currentTarget
          const element = e.getAttribute('data-id')
          toMineDetails(dataList.value)
        }
      })
      // DistrictExplorer_fn(AMap) // 下钻

      //地图加载完成事件
      map.value.on('complete', () => {
        var layer = new AMap.LabelsLayer({
          // 开启标注避让,默认为开启,v1.4.15 新增属性
          collision: false,
          // 开启标注淡入动画,默认为开启,v1.4.15 新增属性
          animation: false
        })
        for (var i = 0; i < LabelsData.length; i++) {
          LabelsData[i].text.style = {
            fillColor: '#777c82'
          }
          var labelsMarker = new AMap.LabelMarker(LabelsData[i])
          layer.add(labelsMarker) // 省份文字
        }
        map.value.add(layer)
        markers_fn(data, AMap) // 散点
      })
      map.value.on('click', (e: any) => {
        map.value.clearInfoWindow()
      })
    })
    .catch((e: any) => {
      console.error(e) //加载错误提示
    })
    .finally(() => {
      loading.value = false
    })
}
//散点标记
const markers_fn = (data: any, AMap: any) => {
  normalMarker.value = new AMap.Marker({
    anchor: 'bottom-center',
    offset: [0, 0]
  })
  labelsLayer.value = new AMap.LabelsLayer({
    zooms: [4.3, 20],
    zIndex: 200,
    // 关闭标注淡入动画
    collision: false,
    // 设置 allowCollision:true,可以让标注避让用户的标注
    allowCollision: false
  })
  map.value.add(labelsLayer.value)

  let icon = {
    type: 'image',
    anchor: 'bottom-center'
  }
  markers.value = []
  data.forEach((item: any, i: number) => {
    let labelMarker = new AMap.LabelMarker({
      title: `${item.mineName}-${item.mineId}`,
      position: [item.longitude, item.latitude],
      zIndex: item.customer === 1 ? 20 : 16,
      icon: {
        image: item.customer === 1 ? imgList.value[0] : imgList.value[1],
        ...icon
      }
    })
    markers.value.push(labelMarker)
    labelMarker.on('mouseover', function (e: any) {
      let strArr = e.data.data.name.split('-')
      let position = e.data.data && e.data.data.position
      let pixel = e.pixel

      normalMarker.value.setContent(
        `<div class="amap-info-window" style="top:${pixel.y}px;left:${pixel.x}px;">
          ${strArr[0]}
          <div class="amap-info-sharp"></div>
        </div>`
      )
      normalMarker.value.setPosition(position)
      map.value.add(normalMarker.value)
    })
    labelMarker.on('mouseout', function () {
      map.value.remove(normalMarker.value)
    })

    labelMarker.on('click', function (e: any) {
      let strArr = e.data.data.name.split('-')
      getMineInfo(strArr[0])
    })
  })
  labelsLayer.value.add(markers.value)
}
</script>

<style scoped lang="scss">
@import './map.scss';
</style>