高德地图展示点位信息

74 阅读2分钟

展示点位信息

image.png

<template>
  <div>
    <div id="map_container" ref="map" style="width:100%;height: 1100px"></div>
  </div>
</template>

<script setup>
import { ref, nextTick } from 'vue'

//地图
const map = ref(null)
//地图实例
const mapInstance = ref(null)
//窗口选择
const poiPickerInstance = ref(null)
//点标记
const markerInstance = ref(null)

let marker = {}
const infoWindowInstance = ref(null)


let initialLatLng = ''
let id = ''
let info = {}
//所有点位的详细信息
let list = {}

//初始化所有点位
function initData(dataList){
  for(let i=0;i<dataList.length;i++){
    if(!dataList[i].lat || !dataList[i].lng){
      continue
    }
    let latLng = [dataList[i].lng,dataList[i].lat]
    list[dataList[i].id] = dataList[i]
    addMarker(latLng,dataList[i].id)
  }
}

// 实例化点标记
function addMarker(latLng,newId) {
  marker[newId]= new AMap.Marker({
    position: latLng,
    offset: new AMap.Pixel(-13, -30)
  });
  marker[newId].setMap(mapInstance.value);
  // 添加点击事件
  marker[newId].on('click', function (event) {
    show(list[newId])
  })
}


//显示单点
const show = (data)=>{
  initialLatLng  = data.lng+','+data.lat
  id = data.id
  info = {
    corpNo:data.corpNo,
    corpName:data.corpName,
    orgName:data.orgName,
    address:data.corpAddress,
    corpLy:data.corpLy,
    corpYy:data.corpYy
  }
  //清除窗口
  resetMapState()
  //绘制窗口
  makeLat()
}

// 统一清理函数
const resetMapState = () => {
  if (poiPickerInstance.value) {
    poiPickerInstance.value.destroy()
    poiPickerInstance.value = null
  }
  clearMapOverlays()
}

// 清理函数
const clearMapOverlays = () => {
  // 关闭信息窗口
  if (infoWindowInstance.value) {
    infoWindowInstance.value.close() // 关键:关闭窗口
    infoWindowInstance.value = null
  }
}

const makeLat = () => {
  nextTick(() => {
    marker[id].setIcon('//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-red.png')

    AMapUI.loadUI(['misc/PoiPicker'], function(PoiPicker) {
      poiPickerInstance.value = new PoiPicker({

        placeSearchOptions: {
          map: mapInstance.value,
          pageSize: 10
        },
      });
      poiPickerReady(poiPickerInstance.value);
    })

    function poiPickerReady(poiPicker) {

      window.poiPicker=null
      window.poiPicker = poiPicker;
      infoWindowInstance.value = null
      infoWindowInstance.value = new AMap.InfoWindow({
        offset: new AMap.Pixel(0, -100),
        isCustom: true,  // 使用自定义窗体
        autoMove: true,  // 是否自动调整窗体到视野内
      });

      if (initialLatLng) {
        const position = new AMap.LngLat(...initialLatLng.split(',').map(Number));
        // console.log(position)
        mapInstance.value.setCenter(marker[id].getPosition());
        // 使用地理编码服务获取地址信息
        const geocoder = new AMap.Geocoder();
        geocoder.getAddress(position, (status, result) => {
          if (status === 'complete' && result.info === 'OK') {
            infoWindowInstance.value.setContent(`
  <div style="
    padding-bottom: 15px;
  ">
    <div style="
      padding: 12px 16px;
      width: 280px;
      background: white;
      border-radius: 8px;
      box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
      transition: all 0.3s ease;
    ">
      <h4 style="
        margin: 0 0 6px 0;
        padding-bottom: 4px;
        border-bottom: 1px solid #eee;
        color: #333;
        font-size: 15px;
      ">📌 点位信息</h4>
      <div style="
        font-size: 13px;
        line-height: 2;
        color: #666;
      ">
        <div><b>户号:</b>${info.corpNo}</div>
        <div><b>名称:</b>${info.corpName}</div>
        <div><b>区域:</b>${info.orgName}</div>
        <div><b>详细地址:</b>${info.address}</div>

        <!-- 流量计 - 开关样式 -->
        <div><b>流量计:</b>
          <span style="
            display: inline-block;
            position: relative;
            vertical-align: middle;
            width: 40px;
            height: 20px;
            margin-left: 8px;
            background: ${info.corpLy === '1' ? '#409EFF' : '#dcdfe6'};
            border-radius: 10px;
            transition: all 0.3s;
          ">
            <span style="
              position: absolute;
              top: 2px;
              left: ${info.corpLy === '1' ? '22px' : '2px'};
              width: 16px;
              height: 16px;
              background: white;
              border-radius: 50%;
              transition: all 0.3s;
              box-shadow: 0 1px 3px rgba(0,0,0,0.2);
            "></span>
          </span>
        </div>

        <!-- 压力 - 开关样式 -->
        <div><b>压力:</b>
          <span style="
            display: inline-block;
            position: relative;
            vertical-align: middle;
            width: 40px;
            height: 20px;
            margin-left: 8px;
            background: ${info.corpYy === '1' ? '#409EFF' : '#dcdfe6'};
            border-radius: 10px;
            transition: all 0.3s;
          ">
            <span style="
              position: absolute;
              top: 2px;
              left: ${info.corpYy === '1' ? '22px' : '2px'};
              width: 16px;
              height: 16px;
              background: white;
              border-radius: 50%;
              transition: all 0.3s;
              box-shadow: 0 1px 3px rgba(0,0,0,0.2);
            "></span>
          </span>
        </div>
      </div>
    </div>

    <!-- 白色下箭头 -->
    <div style="
      position: absolute;
      bottom: 0;
      left: 128px; /* 居中位置 */
      transform: translateX(-50%);
      width: 0;
      height: 0;
      border-left: 10px solid transparent;
      border-right: 10px solid transparent;
      border-top: 15px solid white;
    "></div>
  </div>
`);
            infoWindowInstance.value.setMap(mapInstance.value);
            infoWindowInstance.value.setPosition(position);
            infoWindowInstance.value.open(mapInstance.value, position);
          }
        });

      }
    }
  });
}

onMounted(()=>{
  // 创建地图实例
  mapInstance.value= new AMap.Map(map.value, {
    zoom: 14,
    center: [120.30548699999986, 31.91],
  });
})

defineExpose({
  show,initData
})
</script>





<style>
/* 移除高德地图相关元素 */
.dg, .main, .a{
  display: none;
}
.amap-logo, .amap-copyright {
  display: none !important;
}
</style>