高德地圖API 在vue3 里使用

一,安裝

pnpm install @amap/amap-jsapi-loader

二,使用手冊(cè)

1,vue3 引用,初始化

<template>
  <div id="mechanism-map"></div>
</template>

<script setup lang="ts">
import AMapLoader from '@amap/amap-jsapi-loader'

let map = null
let AMapObj = null

// 地圖初始化
const initMap = async() => {
  try {
    AMapObj = await AMapLoader.load({
      key: import.meta.env.VITE_APP_MAP_KEY,
      version: '2.0',
      plugins: []  // ['AMap.Geocoder', 'AMap.Geolocation'] 定位插件
    })
  } catch (e) {
    console.error('地圖初始化失敗:', e)
  }
}

onMounted(async () => {
  initMap()
})

onUnmounted(() => {
  map?.destroy()
})
</script>

2,地圖顯示

2.1 地圖加載、點(diǎn)擊事件,中心點(diǎn)顯示

// 地圖顯示,并標(biāo)記中心點(diǎn)
const getMarker = (lng, lat) => {
  const lnglat = new AMapObj.LngLat(lng, lat)

  // 地圖
  map = new AMapObj.Map('mechanism-map', {
    viewMode: '2D',
    zoom: 11,
    center: lnglat,
    mapStyle: 'amap://styles/macaron',   // 主題
    showLabel: true,
    showIndoorMap: true
  })

  map.setStatus({
    dragEnable: true,
    zoomEnable: false
  })

  // 添加回到已知位置的按鈕
  setReloadLocal(longitude, latitude)
  // 添加本地位置標(biāo)記
  localMarker(lnglat)
  
  //  地圖點(diǎn)擊事件
  map.on('click', (e) => {
    proxy.$router.push('/mechanism-map')
  })
  
  // 地圖加載完事件
  map.on('complete', onLabelMarker)
}

const initMap = async () => {
  try {
    AMapObj = await AMapLoader.load({
      key: import.meta.env.VITE_APP_MAP_KEY,
      version: '2.0',
      plugins: ['AMap.Geocoder', 'AMap.Geolocation', 'AMap.CitySearch']
    })
    const { longitude, latitude } = proxy.locationInfo

    getMarker(longitude, latitude)
  } catch (e) {
    console.error('地圖初始化失敗:', e)
  }
}

2.2 添加本地位置標(biāo)記

const localMarker = (lnglat) => {
  const icon = new AMapObj.Icon({
    size: new AMapObj.Size(72, 72),
    image: new URL('../../assets/point.png', import.meta.url).href,
    imageSize: new _AMap.Size(26, 26)
  })

  new _AMap.Marker({
    map: map,
    icon, // 擴(kuò)展需要的圖標(biāo),沒有則顯示默認(rèn)的圖標(biāo)
    position: lnglat
  })
  
  map.add(marker)
}

2.3 添加回到已知位置的按鈕

const setReloadLocal = (longitude: number, latitude: number) => {
  const imgDiv = document.createElement('div')
  imgDiv.classList.add('amap-geolocation-reload')
  imgDiv.style.position = 'absolute'
  imgDiv.style.bottom = '100px'
  imgDiv.style.right = '15px'
  imgDiv.style.padding = '4px'
  imgDiv.style.borderRadius = '50px'
  imgDiv.style.background = '#fff'
  imgDiv.style.fontSize = '0'
  imgDiv.style.boxShadow = '0 0 5px silver'
  const imgElement = document.createElement('img')
  imgElement.src = new URL('../../assets/map_position.png', import.meta.url).href
  imgElement.width = 24
  imgElement.height = 24
  imgDiv.appendChild(imgElement)
  document.body.appendChild(imgDiv)

  // 點(diǎn)擊按鈕時(shí)回到已知位置
  imgElement.addEventListener('click', () => {
      const { longitude, latitude } = proxy.locationInfo
      // 設(shè)置地圖中心點(diǎn)
      map?.setCenter([lng || Number(longitude), lat || Number(latitude)])
      // 可選:設(shè)置縮放級(jí)別
      map?.setZoom(11)
  })
}
image.png

2.4 標(biāo)記避讓

標(biāo)注是否避讓,true:避讓,不會(huì)把所有位置相近的點(diǎn)都顯示出來;false:不避讓,把所有點(diǎn)都顯示出來。

const onLabelMarker = () => {
  labelsLayerIcon = new _AMap.LabelsLayer({
    zooms: [2, 20],
    zIndex: 100,
    collision: true // 標(biāo)注是否避讓
  })

  map.add(labelsLayerIcon)

  setLabelMarker()

// 地圖點(diǎn)擊事件
  map.on('click', markerUnBind)
// 地圖加載完成事件
  map.on('complete', () => {
    if (result.value.length > 0) {
      console.log('bbbdddd')
    }
  })
}

// 點(diǎn)擊其他區(qū)域隱藏所有標(biāo)記點(diǎn)的文本和樣式
const markerUnBind = () => {
  markers.forEach((marker) => {
    marker.setIcon({
      size: [24, 24]
    })
  })
  normalMarker && map?.remove(normalMarker)
}

3,AMap.Geolocation 精度定位插件

const getGeolocation = () => {
  try {
    // 初始化定位插件
    map.plugin('AMap.Geolocation', () => {
      const geolocation = new AMapObj.Geolocation({
          enableHighAccuracy: true, //是否使用高精度定位,默認(rèn):true
          timeout: 10000, //超過10秒后停止定位,默認(rèn):無窮大
          maximumAge: 0, //定位結(jié)果緩存0毫秒,默認(rèn):0
          convert: true, //自動(dòng)偏移坐標(biāo),偏移后的坐標(biāo)為高德坐標(biāo),默認(rèn):true
          showButton: true, //顯示定位按鈕,默認(rèn):true
          buttonPosition: 'RB', //定位按鈕??课恢茫J(rèn):'LB',左下角
          buttonOffset: new AMap.Pixel(10, 20), //定位按鈕與設(shè)置的??课恢玫钠屏浚J(rèn):Pixel(10, 20)
          showMarker: true, //定位成功后在定位到的位置顯示點(diǎn)標(biāo)記,默認(rèn):true
          showCircle: true, //定位成功后用圓圈表示定位精度范圍,默認(rèn):true
          panToLocation: true, //定位成功后將定位到的位置作為地圖中心點(diǎn),默認(rèn):true
          zoomToAccuracy: false //定位成功后調(diào)整地圖視野范圍使定位位置及精度范圍視野內(nèi)可見,默認(rèn):false
      })
    
      geolocation.getCurrentPosition((status, result) => {
          if (status === 'complete') {
            console.log('定位成功', result)
          } else {
            console.error('定位失敗', result)
          }
        })
      // 監(jiān)聽定位成功事件
        geolocation.on('complete', (result) => {
          console.log('定位成功', result)
          const { position } = result // 獲取定位結(jié)果
          const lng = position.lng // 經(jīng)度
          const lat = position.lat // 緯度
          console.log(`當(dāng)前位置:經(jīng)度 ${lng},緯度 ${lat}`)
        })

        // 監(jiān)聽定位失敗事件
        geolocation.on('error', (error) => {
          console.error('定位失敗', error)
        })
    }
  } catch(e) {
     console.log('定位失敗', e)    
  }
} 
image.png
image.png

4,逆地理編碼


// 通過經(jīng)緯度獲取地址信息
const getAddress = (lng, lat) => {
  try {
      map.plugin('AMap.Geolocation', () => {
          const geocoder = new AMapObj.Geocoder({
            radius: 1000,
            extensions: 'all'
          })
          geocoder.getAddress([lng, lat], (status, result) => {
            console.log('逆地理編碼結(jié)果', status, result)
            if (status === 'complete' && result.info === 'OK') {
              if (result.regeocode) {
                  // 地址信息
                  console.log('address', result.regeocode.formattedAddress)
              }
            }
          })  
       }
  } catch (e) {
    console.log('')
  }
}

5,AMap.ToolBar 放大縮小地圖插件

工具條只顯示放大縮小按鈕

AMapLoader.load({
    key: import.meta.env.VITE_APP_MAP_KEY,
    version: '2.0',
    plugins: ['AMap.ToolBar']
  })
    .then(async (AMap) => {
      _AMap = AMap

      const { longitude, latitude } = proxy.locationInfo

      const lnglat = new AMap.LngLat(longitude, latitude)

      map = new AMap.Map('mechanism-map', {
        viewMode: '2D',
        zoom: 11,
        center: lnglat,
        showLabel: true,
        showIndoorMap: true
      })

      // 添加工具條控件
      map.addControl(new AMap.ToolBar({
          position: 'RB', // 將工具條顯示在右下角,LT:左上角;LB:左下角;RT:右上角
      }))

      map.on('complete', onLabelMarker)
    })
    .catch((e) => {
      console.error(e)
    })
image.png

6,AMap.LabelMarker 帶標(biāo)簽的標(biāo)記點(diǎn)

6.1 直接顯示標(biāo)點(diǎn)文本

const result = ref([])
result.value = [{
    "type": "1",
    "agmx0100": "1904421574694694913",
    "agmx0101": "大連中山桂林養(yǎng)護(hù)院",
    "agmx0135": "121.66",
    "agmx0136": "38.91"
},
{
    "type": "2",
    "agmx0100": "1904769910488461314",
    "agmx0101": "大連莊河市頤養(yǎng)服務(wù)中心",
    "agmx0135": "122.984648",
    "agmx0136": "39.691699"
},
{
    "type": "3",
    "agmx0100": "1904693894285914113",
    "agmx0101": "大連市椒金山養(yǎng)老服務(wù)中心",
    "agmx0135": "121.608556",
    "agmx0136": "38.978"
},
{
    "type": "4",
    "agmx0100": "1904693894285914113",
    "agmx0101": "大連市椒金山養(yǎng)老服務(wù)中心",
    "agmx0135": "121.608556",
    "agmx0136": "38.978"
}]

let map = null
let _AMap = null
let markers = null
let labelsLayerIcon = null

const onLabelMarker = () => {
  labelsLayerIcon = new _AMap.LabelsLayer({
    zooms: [2, 20],
    zIndex: 100,
    collision: true // 標(biāo)注是否避讓,true:避讓,不會(huì)把所有位置相近的點(diǎn)都顯示出來;false:不避讓,把所有點(diǎn)都顯示出來。
  })
  
  // 將標(biāo)記點(diǎn)添加到地圖上。
  map.add(labelsLayerIcon)

  const textColor = ['#32a5f1', '#25c8b1', '#4922e5', '#ef1530']

  const icons = [
    new URL('./assets/map_mechanism.png', import.meta.url).href,
    new URL('./assets/map_community.png', import.meta.url).href,
    new URL('./assets/map_canteen.png', import.meta.url).href,
    new URL('./assets/map_branches.png', import.meta.url).href
  ]

  result.value.forEach((item) => {
    if (item.agmx0135 && item.agmx0136) {
      let labelMarker = new _AMap.LabelMarker({
        name: '標(biāo)注',
        // 確保經(jīng)緯度是有效的數(shù)字
        position: checkIfRepeatLayer(Number(item.agmx0135), Number(item.agmx0136)).position,
        icon: {
          type: 'image',
          image: icons[Number(item.type) - 1] || icons[0],
          size: [24, 24],
          anchor: 'bottom-center'
        },
        text: {
          content: item.agmx0101,
          direction: 'bottom', // 文字顯示位置,left, right, top, bottom
          style: {
            fold: true, // 支持回行,一行最多6個(gè)字
            fontSize: 12,
            fillColor: textColor[Number(item.type) - 1] || textColor[0]
          }
        },
        // 其他屬性,通過 .getExtData() 獲取
        extData: { ...item, Number(item.agmx0136)).repeat },
        rank: Number(item.type),  // 避讓顯示的層級(jí),最大顯示最上面
        zIndex: Number(item.type)
      })
      markers.push(labelMarker)

      標(biāo)記點(diǎn)擊事件
      labelMarker.on('click', labelMarkerClick)
    }
  })
  
  // labelMarker 統(tǒng)一添加到地圖
  labelsLayerIcon.add(markers)
}

// 點(diǎn)擊標(biāo)記點(diǎn)時(shí)的事件
const labelMarkerClick = (event) => {
  const targetMarker = event.target // 獲取當(dāng)前點(diǎn)擊的標(biāo)記點(diǎn)
  const position = event.data.data && event.data.data.position
  const targetData = targetMarker.getExtData() // 獲取標(biāo)記點(diǎn)的數(shù)據(jù)

  // 點(diǎn)擊一次地圖層級(jí)放大一級(jí)
  if (map.getZoom() < 20) {
    map.zoomIn()
  }
  // 將點(diǎn)擊的圖標(biāo)設(shè)置為中心點(diǎn)
  map.setCenter(position)
}
image.png

6.2 點(diǎn)擊標(biāo)點(diǎn)顯示文本

// 普通提示點(diǎn)
let normalMarker = null

const onLabelMarker = () => {
  labelsLayerIcon = new _AMap.LabelsLayer({
    zooms: [2, 20],
    zIndex: 100,
    collision: true // 標(biāo)注是否避讓
  })

  map.add(labelsLayerIcon)

  const textColor = ['#32a5f1', '#25c8b1', '#4922e5', '#ef1530']

  const icons = [
    new URL('./assets/map_mechanism.png', import.meta.url).href,
    new URL('./assets/map_community.png', import.meta.url).href,
    new URL('./assets/map_canteen.png', import.meta.url).href,
    new URL('./assets/map_branches.png', import.meta.url).href
  ]

  result.value.forEach((item) => {
    if (item.agmx0135 && item.agmx0136) {
      let labelMarker = new _AMap.LabelMarker({
        name: '標(biāo)注',
        position: checkIfRepeatLayer(Number(item.agmx0135), Number(item.agmx0136)).position,
        icon: {
          type: 'image',
          image: icons[Number(item.type) - 1] || icons[0],
          size: [24, 24],
          anchor: 'bottom-center'
        }
        extData: { ...item, Number(item.agmx0136)).repeat },
        rank: Number(item.type),
        zIndex: Number(item.type)
      })
      markers.push(labelMarker)

      labelMarker.on('click', labelMarkerClick)
    }
  })
  labelsLayerIcon.add(markers)

  // 標(biāo)題提示點(diǎn)
  normalMarker = new _AMap.Marker({
     anchor: 'bottom-center',
     offset: [0, -36]
  })

  map.on('click', markerUnBind)
}

// 點(diǎn)擊標(biāo)記點(diǎn)時(shí)的事件
const labelMarkerClick = (event) => {
  const targetMarker = event.target // 獲取當(dāng)前點(diǎn)擊的標(biāo)記點(diǎn)
  const position = event.data.data && event.data.data.position
  const targetData = targetMarker.getExtData() // 獲取標(biāo)記點(diǎn)的數(shù)據(jù)

  // 點(diǎn)擊一次地圖層級(jí)放大一級(jí)
  if (map.getZoom() < 20) {
    map.zoomIn()
  }
  map.setCenter(position)

  markerUnBind()
  
  // 當(dāng)前點(diǎn)擊圖標(biāo)放大
  targetMarker.setIcon({
    size: [28, 28]
  })

  // 點(diǎn)擊彈出文本區(qū)域標(biāo)點(diǎn)
  if (position) {
     normalMarker.setContent('<div class="amap-info-window">' + targetData.agmx0101 + '</div>')
     normalMarker.setPosition(position)
     map.add(normalMarker)
  }
}

// 點(diǎn)擊其他區(qū)域隱藏所有標(biāo)記點(diǎn)的文本和樣式
const markerUnBind = () => {
  markers.forEach((marker) => {
   // 恢復(fù)原點(diǎn)大小
    marker.setIcon({
      size: [24, 24]
    })
  })
  // 移除普通文本顯示標(biāo)記
  normalMarker && map?.remove(normalMarker)
}

<style lang="scss" scoped>
:deep(.amap-info-window) {
    flex: none;
    font-size: 12px;
    background: #8f8f8f;
    color: #fff;
    border-radius: 6px;
    padding: 5px 12px;
    box-shadow: 0 2px 6px 0 rgba(133, 133, 133, 0.5);
    position: relative;

    &::after {
      content: '';
      display: block;
      position: absolute;
      top: 25px;
      bottom: 0;
      left: 50%;
      margin-left: -8px;
      border-left: 8px solid transparent;
      border-right: 8px solid transparent;
      border-top: 8px solid #8f8f8f;
    }
  }
}
</style>
image.png

image.png

7,替換地圖主題

// 主題
mapStyle: 'amap://styles/macaron',  // 馬卡龍
mapStyle: 'amap://styles/whitesmoke'  // 遠(yuǎn)山黛
mapStyle: 'amap://styles/normal'  // 標(biāo)準(zhǔn)
const initMap = () => {
  AMapLoader.load({
    key: import.meta.env.VITE_APP_MAP_KEY,
    version: '2.0',
    plugins: ['AMap.LabelsLayer']
  })
    .then(async (AMap) => {
      _AMap = AMap
      const { longitude, latitude } = proxy.locationInfo
      const lnglat = new AMap.LngLat(longitude, latitude)
      map = new AMap.Map('mechanism-map', {
        viewMode: '2D',
        zoom: 11,
        center: lnglat,
        showLabel: true,
        mapStyle: 'amap://styles/macaron',  // 主題
        labelRejectMask: true,
        showIndoorMap: true
      })
    })
    .catch((e) => {
      console.error(e)
    })
}
image.png

image.png

image.png

8,導(dǎo)航功能

<template>
  <div>
    <div class="intro-content_service">
      <p class="flex-between-center" @click="onMap()">導(dǎo)航至當(dāng)前位置</p>
    </div>

    <van-action-sheet
      v-model:show="mapShow"
      :actions="actions"
      cancel-text="取消"
      close-on-click-action
      @select="openAmapNavigation"
    />
  </div>
</template>

<script setup lang="ts">
const mapShow = ref(false)

const actions = [{ name: '高德地圖' }]

const onMap = () => {
  mapShow.value = true
}

const startLocal = ref(null)
const endLocal = ref(null)

const locationInfo = {
  longitude: 'xxx.xx',
  latitude: 'xxxx.xx',
  address: '當(dāng)前位置地址'
}

const webGaoDeMap = () => {
  try {
    // 瀏覽器端跳轉(zhuǎn)高德
    const [startLng, startLat, startName] = startLocal.value
    const [endLng, endLat, endName] = endLocal.value
    let path = `?from=${startLng},${startLat},${encodeURIComponent(
      startName
    )}&to=${endLng},${endLat},${encodeURIComponent(endName)}&mode=car`

    // 桌面端會(huì)打開網(wǎng)頁版
    const webUrl = `https://uri.amap.com/navigation/${path}`

    window.open(webUrl, '_blank')
  } catch (err) {
    console.error('高德地圖導(dǎo)航異常:', err)
  }
}

// 打開高德地圖導(dǎo)航
const openAmapNavigation = () => {
  startLocal.value = [Number(locationInfo.longitude), Number(locationInfo.latitude), locationInfo.address]

  if (!endLocal.value || endLocal.value.length == 0) {
    console.error('沒有終點(diǎn)地址')
    return
  }

  // 瀏覽器端跳轉(zhuǎn)高德
  webGaoDeMap()
}
</script>

<style lang="scss" scoped></style>

完整代碼

<template>
  <div id="mechanism-map"></div>
</template>

<script setup lang="ts">
import AMapLoader from '@amap/amap-jsapi-loader'

import { fetchMapMechanismAll } from '@/api/business'

interface Props {
  type?: string
}

const props = withDefaults(defineProps<Props>(), {
  type: ''
})

const { proxy } = getCurrentInstance()

let map = null

let _AMap = null

let labelsLayerIcon = null

let markers = []

const result = ref([])

// 普通提示點(diǎn)
let normalMarker = null

watch(
  () => props.type,
  async () => {
    labelsLayerIcon?.remove(markers)

    markerUnBind()

    returnToOrigin()

    markers = []

    await getMapMechanism()

    onLabelMarker()
  }
)

const returnToOrigin = (lng?: number, lat?: number) => {
  const { longitude, latitude } = proxy.locationInfo
  map?.setCenter([lng || Number(longitude), lat || Number(latitude)])
  map?.setZoom(11)
}

const getMapMechanism = async () => {
  try {
    result.value = [
      {
        type: '1',
        agmx0100: '1904421574694694913',
        agmx0101: '大連中山桂林養(yǎng)護(hù)院',
        agmx0135: '121.66',
        agmx0136: '38.91'
      },
      {
        type: '2',
        agmx0100: '1904769910488461314',
        agmx0101: '大連莊河市頤養(yǎng)服務(wù)中心',
        agmx0135: '122.984648',
        agmx0136: '39.691699'
      },
      {
        type: '3',
        agmx0100: '1904693894285914113',
        agmx0101: '大連市椒金山養(yǎng)老服務(wù)中心',
        agmx0135: '121.608556',
        agmx0136: '38.978'
      },
      {
        type: '4',
        agmx0100: '1904693894285914113',
        agmx0101: '大連市椒金山養(yǎng)老服務(wù)中心',
        agmx0135: '121.608556',
        agmx0136: '38.978'
      }
    ]
  } catch (error) {
    console.error(error)
  }
}

const onLabelMarker = () => {
  labelsLayerIcon = new _AMap.LabelsLayer({
    zooms: [2, 20],
    zIndex: 100,
    collision: true // 標(biāo)注是否避讓
  })

  map.add(labelsLayerIcon)

  const textColor = ['#32a5f1', '#25c8b1', '#4922e5', '#ef1530']

  const icons = [
    new URL('./assets/map_mechanism.png', import.meta.url).href,
    new URL('./assets/map_community.png', import.meta.url).href,
    new URL('./assets/map_canteen.png', import.meta.url).href,
    new URL('./assets/map_branches.png', import.meta.url).href
  ]

  result.value.forEach((item) => {
    if (item.agmx0135 && item.agmx0136) {
      let labelMarker = new _AMap.LabelMarker({
        name: '標(biāo)注',
        position: checkIfRepeatLayer(Number(item.agmx0135), Number(item.agmx0136)).position,
        icon: {
          type: 'image',
          image: icons[Number(item.type) - 1] || icons[0],
          size: [24, 24],
          anchor: 'bottom-center'
        },
        text: {
          content: item.agmx0101,
          direction: 'bottom',
          style: {
            fontSize: 12,
            fillColor: textColor[Number(item.type) - 1] || textColor[0]
          }
        },
        extData: { ...item, repeat: checkIfRepeatLayer(Number(item.agmx0135), Number(item.agmx0136)).repeat },
        rank: Number(item.type),
        zIndex: Number(item.type)
      })
      markers.push(labelMarker)

      labelMarker.on('click', labelMarkerClick)
    }
  })
  labelsLayerIcon.add(markers)

  // // 標(biāo)題提示點(diǎn)
  // normalMarker = new _AMap.Marker({
  //   anchor: 'top-center',
  //   offset: [0, -36]
  // })

  map.on('click', markerUnBind)
}

// 判斷標(biāo)記點(diǎn)是否經(jīng)緯度一樣
const checkIfRepeatLayer = (lng: number, lat: number) => {
  let newLng = lng
  let newLat = lat
  // 篩選出位于目標(biāo)位置的所有標(biāo)記點(diǎn)
  const overlappedMarkers = markers.filter((marker) => {
    const position = marker.getPosition()
    return position.lng === lng && position.lat === lat
  })
  if (overlappedMarkers.length > 0) {
    newLng = Number(overlappedMarkers[overlappedMarkers.length - 1].getPosition().lng) + 0.00003
  }

  return {
    position: [newLng, newLat],
    repeat: overlappedMarkers.length > 0 ? true : false
  }
}

// 點(diǎn)擊標(biāo)記點(diǎn)時(shí)的事件
const labelMarkerClick = (event) => {
  const targetMarker = event.target // 獲取當(dāng)前點(diǎn)擊的標(biāo)記點(diǎn)
  const position = event.data.data && event.data.data.position
  const targetData = targetMarker.getExtData() // 獲取標(biāo)記點(diǎn)的數(shù)據(jù)

  // 點(diǎn)擊一次地圖層級(jí)放大一級(jí)
  if (map.getZoom() < 20) {
    map.zoomIn()
  }
  // targetData.repeat && map.setZoom(20) // 如果有重復(fù)的標(biāo)記點(diǎn),放大地圖
  map.setCenter(position)

  markerUnBind()

  targetMarker.setIcon({
    size: [28, 28]
  })

  // 點(diǎn)擊彈出文本區(qū)域標(biāo)點(diǎn)
  // if (position) {
  //   normalMarker.setContent('<div class="amap-info-window">' + targetData.agmx0101 + '</div>')
  //   normalMarker.setPosition(position)
  //   map.add(normalMarker)
  // }
}

// 點(diǎn)擊其他區(qū)域隱藏所有標(biāo)記點(diǎn)的文本和樣式
const markerUnBind = () => {
  markers.forEach((marker) => {
    marker.setIcon({
      size: [22, 22]
    })
  })
  normalMarker && map?.remove(normalMarker)
  emitter.emit('onVisibleState', false)
}

// 添加本地位置標(biāo)記
const localMarker = (longitude: number, latitude: number) => {
  const icon = new _AMap.Icon({
    size: new _AMap.Size(72, 72),
    image: new URL('../../assets/point.png', import.meta.url).href,
    imageSize: new _AMap.Size(26, 26)
  })

  new _AMap.Marker({
    map: map,
    icon,
    position: [longitude, latitude]
  })
}

// 添加回到已知位置的按鈕
const setReloadLocal = (longitude: number, latitude: number) => {
  const imgDiv = document.createElement('div')
  imgDiv.classList.add('amap-geolocation-reload')
  imgDiv.style.position = 'absolute'
  imgDiv.style.bottom = '100px'
  imgDiv.style.right = '15px'
  imgDiv.style.padding = '4px'
  imgDiv.style.borderRadius = '50px'
  imgDiv.style.background = '#fff'
  imgDiv.style.fontSize = '0'
  imgDiv.style.boxShadow = '0 0 5px silver'
  const imgElement = document.createElement('img')
  imgElement.src = new URL('../../assets/map_position.png', import.meta.url).href
  imgElement.width = 24
  imgElement.height = 24
  imgDiv.appendChild(imgElement)
  document.body.appendChild(imgDiv)

  // 點(diǎn)擊按鈕時(shí)回到已知位置
  imgElement.addEventListener('click', () => {
    returnToOrigin(longitude, latitude)
  })
}

const initMap = () => {
  AMapLoader.load({
    key: import.meta.env.VITE_APP_MAP_KEY,
    version: '2.0',
    plugins: ['AMap.Geolocation']
  })
    .then(async (AMap) => {
      _AMap = AMap

      const { longitude, latitude } = proxy.locationInfo

      const lnglat = new AMap.LngLat(longitude, latitude)

      map = new AMap.Map('mechanism-map', {
        viewMode: '2D',
        zoom: 11,
        center: lnglat,
        showLabel: true,
        showIndoorMap: true
      })

      setReloadLocal(longitude, latitude)
      localMarker(Number(longitude), Number(latitude))

      map.on('complete', onLabelMarker)
    })
    .catch((e) => {
      console.error(e)
    })
}

onMounted(async () => {
  await getMapMechanism()

  initMap()
})

onUnmounted(() => {
  map?.destroy()
  const elements = document.querySelectorAll('.amap-geolocation-reload')
  elements.forEach((element) => {
    element?.remove() // 移除每個(gè)匹配的元素
  })
})
</script>
<style lang="scss" scoped>
#mechanism-map {
  :deep(.amap-toolbar) {
    bottom: 110px !important;
  }
  :deep(.amap-geolocation) {
    bottom: 100px !important;
  }
  :deep(.amap-marker) {
    display: flex !important;
    justify-content: center;
    align-items: center;
  }
  :deep(.amap-info-window) {
    flex: none;
    font-size: 12px;
    background: #8f8f8f;
    color: #fff;
    border-radius: 6px;
    padding: 5px 12px;
    box-shadow: 0 2px 6px 0 rgba(133, 133, 133, 0.5);
    position: relative;

    &::after {
      content: '';
      display: block;
      position: absolute;
      top: 25px;
      bottom: 0;
      left: 50%;
      margin-left: -8px;
      border-left: 8px solid transparent;
      border-right: 8px solid transparent;
      border-top: 8px solid #8f8f8f;
    }
  }
}
</style>
<style scoped>
#mechanism-map {
  width: 100%;
  height: 100vh;
}
</style>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容