欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue3實現(xiàn)地圖選點組件的示例代碼

 更新時間:2024年01月04日 11:51:26   作者:liyfn  
這篇文章主要為大家詳細介紹了Vue3實現(xiàn)地圖選點組件的相關(guān)知識,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下

Vue3地圖選點組件

實現(xiàn)代碼

<template>
  <div style="width: 100%; height: 500px">
    <div class="search-container">
      <el-autocomplete
        v-model="suggestionKeyWord"
        class="search-container__input"
        clearable
        :fetch-suggestions="searchSuggestions"
        placeholder="輸入關(guān)鍵字搜索"
        @select="onSuggestionChoose"
      >
        <template #default="{ item }">
          <div class="value">{{ item.name }}</div>
          <span class="link">{{ item.address }}</span>
        </template>
      </el-autocomplete>
      <el-button type="primary" class="search-container__button" @click="doneMap"> 確定 </el-button>
    </div>
    <div class="map-body">
      <div id="container" class="map-body__left"></div>
      <img :class="iconClass" :src="markerSrc" alt="" />
      <!-- poi數(shù)據(jù) -->
      <div class="map-body__right ele-map-picker-poi-list">
        <div
          v-for="(poi, index) in poiData"
          :key="index"
          :class="[
            'ele-map-picker-poi-item',
            { 'ele-map-picker-poi-item-active': index === chooseIndex },
          ]"
          @click="choose(index)"
        >
          <el-icon class="ele-map-picker-poi-item-icon el-icon-location-outline"
            ><Location
          /></el-icon>
          <!-- <icon-ep-location class="ele-map-picker-poi-item-icon el-icon-location-outline" /> -->
          <div class="ele-map-picker-poi-item-title">{{ poi.name }}</div>
          <div v-if="poi.address" class="ele-map-picker-poi-item-address">
            {{ poi.address }}
          </div>
          <el-icon v-if="index === chooseIndex" class="ele-map-picker-poi-item-check"
            ><Check
          /></el-icon>
          <!-- <icon-park-check-small
            v-if="index === chooseIndex"
            class="ele-map-picker-poi-item-check"
          /> -->
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
  import { onMounted } from 'vue';
  import AMapLoader from '@amap/amap-jsapi-loader';
  import markerSrc from '@/assets/images/location.png';
  import type { Poi } from './type';

  // const props = defineProps({});
  const emit = defineEmits(['done-map']);

  // 中心點位置
  let location: any = reactive([116.4074, 39.9042]);
  // 地圖縮放比例
  const chooseZoom = 15;

  // 搜索關(guān)鍵字
  const suggestionKeyWord = ref('');
  // 搜索建議列表
  let suggestionData = reactive([]);
  // 地圖實例
  let map: any;
  // 輸入建議實例
  let autoComplete = reactive({});
  // 選中的建議
  let chooseSuggestion = reactive<any>({});
  // 地圖中心標記點
  let centerMarker = reactive({});
  // poi檢索實例
  let placeSearch = reactive({});
  // poi檢索的數(shù)據(jù)
  const poiData = ref<Poi[]>([]);
  // 選中的數(shù)據(jù)
  const chooseIndex = ref<any>(null);
  // 是否是點擊poi列表移動地圖
  let isSelMove = false;
  // 圖標是否顯示跳動動畫
  const showIconAnim = ref(false);

  const iconClass = computed(() => {
    return ['ele-map-picker-main-icon', { 'ele-map-picker-anim-bounce': showIconAnim.value }];
  });

  /**
   * @description: 初始化地圖
   * @param {*} local
   * @return {*}
   */
  const initMap = (local: any) => {
    AMapLoader.load({
      key: 'xxxxxxxxxxxxx', // 申請好的Web端開發(fā)者Key,首次調(diào)用 load 時必填
      version: '2.0', // 指定要加載的 JSAPI 的版本,缺省時默認為 1.4.15
      plugins: ['AMap.Geocoder', 'AMap.PlaceSearch', 'AMap.AutoComplete'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
    }).then((AMap) => {
      map = new AMap.Map('container', {
        zoom: chooseZoom,
        center: location,
      });

      // 輸入建議實例
      autoComplete = new AMap.AutoComplete({
        city: '全國',
      });

      // marker實例
      centerMarker = new AMap.Marker({
        icon: new AMap.Icon({
          image: markerSrc,
          size: new AMap.Size(26, 36.5),
          imageSize: new AMap.Size(26, 36.5),
        }),
        offset: new AMap.Pixel(-13, -36.5),
      });
      addMarker(location[0], location[1]);

      // 獲取poi檢索實例
      placeSearch = new AMap.PlaceSearch({
        type: '', // poi檢索興趣點類別
        pageSize: 30, // poi檢索每頁數(shù)量
        pageIndex: 1,
        extensions: 'all',
      });

      // 地圖加載完成事件
      map.on('complete', () => {
        chooseIndex.value = null;
        const center = map.getCenter();
        searchNearBy(center.lat, center.lng, true);
      });

      // 地圖移動結(jié)束事件
      map.on('moveend', () => {
        const center = map.getCenter();
        addMarker(center.lng, center.lat);
        if (isSelMove) {
          // poi列表點擊的移動
          isSelMove = false;
        } else {
          // 拖動或搜索建議的移動
          showIconAnim.value = false;
          nextTick(() => {
            setTimeout(() => {
              showIconAnim.value = true;
            }, 0);
          });
          searchNearBy(center.lat, center.lng);
        }
      });
    });
  };
  /**
   * @description: poi檢索
   * @param {*} lat
   * @param {*} lng
   * @param {*} force
   * @return {*}
   */
  const searchNearBy = (lat: any, lng: any) => {
    if (!placeSearch) {
      return;
    }
    // this.poiLoading = true;
    placeSearch.searchNearBy('', [lng, lat], 1000, (status: any, result: any) => {
      // this.poiLoading = false;
      if (status === 'complete') {
        const data = result.poiList.pois.filter((p: any) => p.location !== undefined);
        if (chooseSuggestion) {
          // 如果選中的搜索建議不在poi列表中則添加
          if (data.length === 0 || data[0].name !== chooseSuggestion.name) {
            data.unshift({ ...chooseSuggestion });
          }
          chooseSuggestion = null;
        } else {
          chooseIndex.value = null;
        }

        poiData.value = data;
        // v3.17 標準地址庫-地址拼接省市區(qū)
        poiData.value.forEach((item) => {
          item.pname = item.pname || '';
          item.cityname = item.cityname || '';
          item.adname = item.adname || '';
          item.address = item.address || '';
          item.address = `${item.pname}${item.cityname}${item.adname}${item.address}`;
        });
      }
    });
  };

  /**
   * @description: poi列表選中
   * @param {*} index
   * @return {*}
   */
  const choose = (index: number) => {
    chooseIndex.value = index;
    isSelMove = true;
    // this.showIconAnim = false;
    // nextTick(() => {
    //     setTimeout(() => {
    //         this.showIconAnim = true;
    //     }, 0);
    // });
    const point = poiData.value[index].location;
    map.setZoomAndCenter(chooseZoom, [point.lng, point.lat]);
  };

  /**
   * @description: 添加marker
   * @param {*} lng
   * @param {*} lat
   * @return {*}
   */
  const addMarker = (lng: string, lat: string) => {
    // centerMarker.setMap(map);
    centerMarker.setPosition([lng, lat]);
    map.add(centerMarker);
  };

  /**
   * @description: 獲取搜索數(shù)據(jù)
   * @param {*} keywords
   * @param {*} callback
   * @return {*}
   */
  const searchSuggestions = (keywords: string, callback: any) => {
    if (!keywords) {
      return callback(suggestionData);
    }
    autoComplete.search(keywords, (status: any, result: any) => {
      if (status === 'complete') {
        suggestionData = result.tips.filter((item) => item.location);

        suggestionData.forEach((item: any) => {
          item.address = item.address || '';
          item.district = item.district || '';
          item.address = `${item.district}${item.address}`;
        });
        callback(suggestionData);
      }
    });
  };

  /**
   * @description: 點擊選擇
   * @param {*} item
   * @return {*}
   */
  const onSuggestionChoose = (item: any) => {
    suggestionKeyWord.value = item.name;
    chooseSuggestion = item;
    chooseIndex.value = 0;

    const point = item.location;
    if (point) {
      map.setZoomAndCenter(chooseZoom, [point.lng, point.lat]);
      addMarker(point.lng, point.lat);
    }
  };

  /**
   * @description: 確定
   * @return {*}
   */
  const doneMap = () => {
    // 地圖中心點
    // const center = { ...map.getCenter() };
    // getByLatLng({ lat: center.lat, lng: center.lng }).then((res) => {
    //   // console.log('接口獲取的值', res);
    //   if (res.result) {
    //     location = {
    //       country: res.result?.country?.i18nName,
    //       province: res.result?.province?.i18nName || '',
    //       city: res.result?.city?.i18nName,
    //       district: res.result?.district?.i18nName,
    //       address: res.result.raw?.formattedAddress,
    //       lat: center.lat,
    //       lng: center.lng,
    //     };
    //   }
    //   // 選中則取高德地圖返回的address
    //   if (chooseIndex.value || chooseIndex.value === 0) {
    //     location.address = poiData.value[chooseIndex.value].address || '';
    //   }
    //   suggestionKeyWord.value = '';
    //   emit('done-map', location);
    // });

    // TODO 由于數(shù)據(jù)規(guī)范性,需獲取經(jīng)緯度后重新請求三級地址
    if (chooseIndex.value || chooseIndex.value === 0) {
      location.address = poiData.value[chooseIndex.value].address || '';
    }
    console.log('選中的地址', location);
    suggestionKeyWord.value = '';
    emit('done-map', location);
  };

  onMounted(() => {
    setTimeout(() => {
      initMap(location);
    }, 200);
  });
</script>

<style scoped lang="scss">
  #container {
    margin: 0;
    padding: 0;
    width: 100%;
    height: calc(100% - 50px);
  }
  .search-container {
    display: flex;
    justify-content: space-between;
    margin-bottom: 10px;
    :deep(.el-autocomplete) {
      width: 80%;
    }
  }
  .map-body {
    display: flex;
    height: 450px;
    &__left {
      width: 70% !important;
      height: 100% !important;
    }
    &__right {
      flex: 1;
    }
  }

  /* 地圖圖標跳動動畫 */
  .ele-map-picker-anim-bounce {
    animation: elePickerAnimBounce 500ms;
    animation-direction: alternate;
  }

  @keyframes elePickerAnimBounce {
    0%,
    60%,
    75%,
    90%,
    to {
      transition-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    }
    0%,
    to {
      transform: translate3d(0, 0, 0);
    }
    25% {
      transform: translate3d(0, -10px, 0);
    }
    50% {
      transform: translate3d(0, -20px, 0);
    }
    75% {
      transform: translate3d(0, -10px, 0);
    }
  }

  .ele-map-picker-main-icon {
    width: 26px;
    position: absolute;
    left: 50%;
    bottom: 50%;
    margin-left: -13px;
  }

  /* poi列表 */
  .ele-map-picker-poi-list {
    overflow: auto;
    width: 300px;
  }
  .ele-map-picker-poi-item {
    position: relative;
    padding: 8px 30px 8px 44px;
    border-bottom: 1px solid hsl(0deg 0% 60% / 15%);
    cursor: pointer;
  }
  .ele-map-picker-poi-item:hover {
    background-color: hsl(0deg 0% 60% / 5%);
  }
  .ele-map-picker-poi-item-icon {
    position: absolute;
    top: 50%;
    left: 14px;
    transform: translateY(-50%);
    font-size: 20px;
    opacity: 0.4;
  }
  .ele-map-picker-poi-item-title {
    font-size: 14px;
  }
  .ele-map-picker-poi-item-address {
    margin-top: 2px;
    font-size: 12px;
    opacity: 0.6;
  }
  .ele-map-picker-poi-item .ele-map-picker-poi-item-check {
    position: absolute;
    top: 50%;
    right: 7px;
    display: none;
    font-size: 16px;
    color: #3b74ff;
    transform: translateY(-50%);
  }
  .ele-map-picker-poi-item-active .ele-map-picker-poi-item-check {
    display: block;
  }
</style>
<style lang="scss">
  .map-body {
    .amap-icon {
      display: none;
    }
  }
</style>

到此這篇關(guān)于Vue3實現(xiàn)地圖選點組件的示例代碼的文章就介紹到這了,更多相關(guān)Vue3地圖選點組件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue+elementUi中的table實現(xiàn)跨頁多選功能(示例詳解)

    vue+elementUi中的table實現(xiàn)跨頁多選功能(示例詳解)

    最近在開發(fā)工業(yè)品超市的后臺系統(tǒng),遇到一個需求,就是實現(xiàn)在一個table表格中多選數(shù)據(jù),在網(wǎng)上查了好多,有些方法真的是無語,下面通過本文給大家分享vue+elementUi中的table實現(xiàn)跨頁多選功能,感興趣的朋友跟隨小編一起看看吧
    2024-05-05
  • vue3 非父子組件通信詳解

    vue3 非父子組件通信詳解

    本篇文章主要介紹了詳解Vue 非父子組件通信,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2021-10-10
  • vue?使用el-table循環(huán)生成表格的過程

    vue?使用el-table循環(huán)生成表格的過程

    這篇文章主要介紹了vue?使用el-table循環(huán)生成表格的過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • Vue加入購物車判斷token添加登錄提示功能

    Vue加入購物車判斷token添加登錄提示功能

    加入購物車,是一個登錄后的用戶 才能進行的操作,所以需要進行鑒權(quán)判斷,判斷用戶token是否存在,這篇文章主要介紹了Vue加入購物車判斷token添加登錄提示,需要的朋友可以參考下
    2023-11-11
  • vue路由跳轉(zhuǎn)時判斷用戶是否登錄功能的實現(xiàn)

    vue路由跳轉(zhuǎn)時判斷用戶是否登錄功能的實現(xiàn)

    下面小編就為大家?guī)硪黄獀ue路由跳轉(zhuǎn)時判斷用戶是否登錄功能的實現(xiàn)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • vue中axios的get請求和post請求的傳參方式、攔截器示例代碼

    vue中axios的get請求和post請求的傳參方式、攔截器示例代碼

    Post是向服務器提交數(shù)據(jù)的一種請求,get是向服務器發(fā)索取數(shù)據(jù)的一種請求,post在真正接受數(shù)據(jù)之前會先將請求頭發(fā)送給服務器進行確認,然后才真正發(fā)送數(shù)據(jù),本文給大家介紹vue中axios的get請求和post請求的傳參方式、攔截器示例代碼,感興趣的朋友一起看看吧
    2023-10-10
  • Element Rate 評分的使用方法

    Element Rate 評分的使用方法

    這篇文章主要介紹了Element Rate 評分的使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-07-07
  • 前端架構(gòu)vue架構(gòu)插槽slot使用教程

    前端架構(gòu)vue架構(gòu)插槽slot使用教程

    這篇文章主要為大家介紹了前端vue架構(gòu)插槽slot使用教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-02-02
  • vue 解決computed修改data數(shù)據(jù)的問題

    vue 解決computed修改data數(shù)據(jù)的問題

    今天小編就為大家分享一篇vue 解決computed修改data數(shù)據(jù)的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • 解讀Vue實例的屬性及模板渲染

    解讀Vue實例的屬性及模板渲染

    這篇文章主要介紹了解讀Vue實例的屬性及模板渲染問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12

最新評論