最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

Vue3地圖選點(diǎn)組件

實(shí)現(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']);

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

  // 搜索關(guān)鍵字
  const suggestionKeyWord = ref('');
  // 搜索建議列表
  let suggestionData = reactive([]);
  // 地圖實(shí)例
  let map: any;
  // 輸入建議實(shí)例
  let autoComplete = reactive({});
  // 選中的建議
  let chooseSuggestion = reactive<any>({});
  // 地圖中心標(biāo)記點(diǎn)
  let centerMarker = reactive({});
  // poi檢索實(shí)例
  let placeSearch = reactive({});
  // poi檢索的數(shù)據(jù)
  const poiData = ref<Poi[]>([]);
  // 選中的數(shù)據(jù)
  const chooseIndex = ref<any>(null);
  // 是否是點(diǎn)擊poi列表移動(dòng)地圖
  let isSelMove = false;
  // 圖標(biāo)是否顯示跳動(dòng)動(dòng)畫
  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', // 申請(qǐng)好的Web端開發(fā)者Key,首次調(diào)用 load 時(shí)必填
      version: '2.0', // 指定要加載的 JSAPI 的版本,缺省時(shí)默認(rèn)為 1.4.15
      plugins: ['AMap.Geocoder', 'AMap.PlaceSearch', 'AMap.AutoComplete'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
    }).then((AMap) => {
      map = new AMap.Map('container', {
        zoom: chooseZoom,
        center: location,
      });

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

      // marker實(shí)例
      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檢索實(shí)例
      placeSearch = new AMap.PlaceSearch({
        type: '', // poi檢索興趣點(diǎn)類別
        pageSize: 30, // poi檢索每頁數(shù)量
        pageIndex: 1,
        extensions: 'all',
      });

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

      // 地圖移動(dòng)結(jié)束事件
      map.on('moveend', () => {
        const center = map.getCenter();
        addMarker(center.lng, center.lat);
        if (isSelMove) {
          // poi列表點(diǎn)擊的移動(dòng)
          isSelMove = false;
        } else {
          // 拖動(dòng)或搜索建議的移動(dòng)
          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 標(biāo)準(zhǔn)地址庫-地址拼接省市區(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: 點(diǎn)擊選擇
   * @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 = () => {
    // 地圖中心點(diǎn)
    // 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)緯度后重新請(qǐng)求三級(jí)地址
    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;
    }
  }

  /* 地圖圖標(biāo)跳動(dòng)動(dòng)畫 */
  .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實(shí)現(xiàn)地圖選點(diǎn)組件的示例代碼的文章就介紹到這了,更多相關(guān)Vue3地圖選點(diǎn)組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue3中引入使用vant組件的教程詳解

    Vue3中引入使用vant組件的教程詳解

    Vant是一個(gè)強(qiáng)大的移動(dòng)端組件庫,目前Vant 官方提供了 Vue 2 版本,Vue 3 版本和微信小程序版本,本文主要為大家介紹vue3中的vant組件引入使用的方法,希望對(duì)大家有所幫助
    2023-10-10
  • vue給對(duì)象動(dòng)態(tài)添加屬性和值的實(shí)例

    vue給對(duì)象動(dòng)態(tài)添加屬性和值的實(shí)例

    今天小編就為大家分享一篇vue給對(duì)象動(dòng)態(tài)添加屬性和值的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-09-09
  • vue中自定義右鍵菜單插件

    vue中自定義右鍵菜單插件

    這篇文章主要為大家詳細(xì)介紹了vue中自定義右鍵菜單插件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • laravel+vue組合的項(xiàng)目中引入ueditor方式(打包成組件形式)

    laravel+vue組合的項(xiàng)目中引入ueditor方式(打包成組件形式)

    今天小編就為大家分享一篇laravel+vue組合的項(xiàng)目中引入ueditor方式(打包成組件形式),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • Vue3實(shí)現(xiàn)跨頁面?zhèn)髦档膸追N常見方法

    Vue3實(shí)現(xiàn)跨頁面?zhèn)髦档膸追N常見方法

    在Vue 3中,跨頁面?zhèn)髦悼梢酝ㄟ^多種方式實(shí)現(xiàn),具體選擇哪種方法取決于應(yīng)用的具體需求和頁面間的關(guān)系,本文列舉了幾種常見的跨頁面?zhèn)髦捣椒?感興趣的同學(xué)跟著小編來看看吧
    2024-04-04
  • vue如何將style私有化

    vue如何將style私有化

    在?Vue.js?中,你可以通過多種方式將樣式私有化,以確保樣式只作用于特定的組件,避免全局污染,本文整理了一些常用的方法,希望對(duì)大家有所幫助
    2024-11-11
  • 解決父組件將子組件作為彈窗調(diào)用只執(zhí)行一次created的問題

    解決父組件將子組件作為彈窗調(diào)用只執(zhí)行一次created的問題

    這篇文章主要介紹了解決父組件將子組件作為彈窗調(diào)用只執(zhí)行一次created的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • Vue中如何避免props驗(yàn)證失敗問題

    Vue中如何避免props驗(yàn)證失敗問題

    本文將探討 props 驗(yàn)證失敗的常見原因,并提供解決方法,幫助開發(fā)者在 Vue 組件開發(fā)中避免這些問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • vue用h()函數(shù)創(chuàng)建Vnodes的實(shí)現(xiàn)

    vue用h()函數(shù)創(chuàng)建Vnodes的實(shí)現(xiàn)

    Vue提供了一個(gè)h()函數(shù)用于創(chuàng)建vnodes,本文就來介紹一下vue用h()函數(shù)創(chuàng)建Vnodes的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Nuxt.js之自動(dòng)路由原理的實(shí)現(xiàn)方法

    Nuxt.js之自動(dòng)路由原理的實(shí)現(xiàn)方法

    這篇文章主要介紹了Nuxt.js之自動(dòng)路由原理的實(shí)現(xiàn)方法,nuxt.js會(huì)根據(jù)pages目錄結(jié)構(gòu)自動(dòng)生成vue-router模塊的路由配置。非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-11-11

最新評(píng)論

介休市| 常熟市| 浏阳市| 德钦县| 龙山县| 宜丰县| 东至县| 武胜县| 安国市| 津市市| 金寨县| 巴中市| 安宁市| 荔波县| 内丘县| 蚌埠市| 蒙阴县| 资阳市| 隆安县| 海南省| 台南市| 竹北市| 昆明市| 南乐县| 荣成市| 临安市| 保靖县| 凤台县| 白河县| 米脂县| 尉犁县| 海阳市| 浮梁县| 建德市| 宾川县| 调兵山市| 新昌县| 清水河县| 巢湖市| 海南省| 哈密市|