소스 검색

地图公共组件

DESKTOP-SVI9JE1\muzen 1 년 전
부모
커밋
91786a166d
1개의 변경된 파일281개의 추가작업 그리고 0개의 파일을 삭제
  1. 281 0
      src/components/Map/index.vue

+ 281 - 0
src/components/Map/index.vue

@@ -0,0 +1,281 @@
+<template>
+  <div class="map">
+    <!-- 搜索 -->
+    <el-form inline size="mini">
+      <el-form-item label="关键词:">
+        <el-autocomplete popper-class="map-popper" v-model="keywords" placeholder="请输入关键词"
+          :fetch-suggestions="getKeyWords" @select="handleSelect" />
+      </el-form-item>
+      <el-form-item style="float: right;">
+        <el-button type="primary" :disabled="activeItem === null" @click="getEmit">确定</el-button>
+      </el-form-item>
+    </el-form>
+    <div class="main">
+      <!-- 地图 -->
+      <div id="container" />
+      <!-- poi列表 -->
+      <div class="poi">
+        <div class="list" v-for="item in poiList" :key="item.id" @click="handleCheck(item)">
+          <div class="name">{{ item.name }}</div>
+          <div class="address">{{ item.address }}</div>
+          <i v-show="activeItem == item" class="el-icon-check" />
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+// 安全密钥
+import AMapLoader from '@amap/amap-jsapi-loader'
+import axios from 'axios'
+window._AMapSecurityConfig = {
+  securityJsCode: 'fd78b73eba80ab3f887c9ba60744048f'
+}
+export default {
+  data() {
+    return {
+      // 地图
+      map: null,
+      // 定位
+      geolocation: null,
+      // 中心坐标
+      location: '',
+      // 关键词
+      keywords: '',
+      // poi列表
+      poiList: [],
+      // 选中的数据
+      activeItem: null
+    }
+  },
+  mounted() {
+    this.initAMap()
+  },
+  methods: {
+    async initAMap() {
+      const that = this
+      // 调用高德
+      const AMap = await this.getMapLoader()
+      // 自定义定位按钮
+      this.geolocation = new AMap.Geolocation({
+        enableHighAccuracy: true, // 高精度定位
+        timeout: 3000, // 定位超时时间
+        zoomToAccuracy: true, // 定位成功后再调整视野
+        showCircle: false, // 定位成功有个圆形范围
+        buttonPosition: 'RB', // 按钮位置
+      })
+      const locationRes = await this.getLocation(AMap)
+      // 当前定位
+      const lnglat = locationRes.status === 'complete' ? [locationRes.data.position.lng, locationRes.data.position.lat] : [116.397428, 39.90923]
+      this.location = lnglat.join(',')
+      // 获取城市信息
+      this.getGeocoder(AMap, lnglat)
+      // 绘制地图
+      this.map = new AMap.Map('container', {
+        resizeEnable: true,
+        zoom: 16,
+        resizeEnable: true,
+        center: lnglat
+      })
+      // 调用插件
+      this.map.addControl(this.geolocation)
+      // 地图加载完
+      this.map.on('complete', function () {
+        // 自动定位一次
+        that.geolocation.getCurrentPosition()
+        that.getPOI()
+      })
+    },
+
+    // 调用高德
+    getMapLoader() {
+      return new Promise((resolve, reject) => {
+        AMapLoader.load({
+          key: '5dcf4cf0260059dade51d0d9b5e3c1ef',
+          version: '2.0',
+          plugins: ['AMap.Geolocation', 'AMap.Geocoder']
+        }).then((AMap) => {
+          resolve(AMap)
+        }).catch((err) => {
+          reject(err)
+        })
+      })
+    },
+
+    // 获取定位
+    getLocation(AMap) {
+      const that = this
+      return new Promise((resolve, reject) => {
+        AMap.plugin('AMap.Geolocation', function () {
+          that.geolocation.getCurrentPosition(function (status, res) {
+            resolve({
+              status: status,
+              data: res
+            })
+          })
+        })
+      })
+    },
+
+    // 获取城市信息
+    getGeocoder(AMap, lnglat) {
+      const that = this
+      AMap.plugin('AMap.Geocoder', function () {
+        var geocoder = new AMap.Geocoder()
+        geocoder.getAddress(lnglat, function (status, res) {
+          let e = res.regeocode.addressComponent
+          that.$emit('address', {
+            status: status,
+            data: e.city ? e.city : e.province
+          })
+        })
+      })
+    },
+
+    // 关键词
+    getKeyWords(query, callback) {
+      let pois = []
+      setTimeout(function () {
+        axios({
+          url: `https://restapi.amap.com/v5/place/text?parameters`,
+          method: 'get',
+          params: {
+            key: '4f11c381b38ea489461aac7451d353ca',
+            keywords: query
+          }
+        }).then(res => {
+          if (res.data.status === '1') {
+            res.data.pois.map(i => {
+              pois.push({
+                ...i,
+                value: `${i.name}(${i.cityname}${i.adname})`
+              })
+            })
+            callback(pois)
+          }
+        })
+      }, 500)
+    },
+
+    // 获取POI
+    getPOI() {
+      axios({
+        url: `https://restapi.amap.com/v5/place/around?parameters`,
+        method: 'get',
+        params: {
+          key: '4f11c381b38ea489461aac7451d353ca',
+          location: this.location
+        }
+      }).then(res => {
+        if (res.data.status === "1") {
+          this.poiList = res.data.pois
+        }
+      })
+    },
+
+    // 选中搜索结果
+    handleSelect(item) {
+      let lng = Number(item.location.split(',')[0])
+      let lat = Number(item.location.split(',')[1])
+      this.location = item.location
+      let marker = new AMap.Marker({
+        position: [lng, lat]
+      })
+      this.map.add(marker)
+      this.map.setCenter([lng, lat])
+      this.getPOI()
+    },
+
+    // 选中poi
+    handleCheck(item) {
+      this.activeItem = item
+    },
+
+    getEmit() {
+      this.$emit('data', this.activeItem)
+    }
+  }
+}
+</script>
+
+<style lang="scss">
+.map-popper {
+  width: 500px !important;
+}
+</style>
+
+<style lang="scss" scoped>
+.map {
+  display: flex;
+  flex-direction: column;
+
+  .el-form {
+    padding: 0 15px;
+
+    .el-form-item {
+      margin: 0;
+    }
+  }
+
+  .main {
+    display: flex;
+    border: 1px solid #e8e8e8;
+
+    #container {
+      padding: 0px;
+      margin: 0px;
+      width: 480px;
+      height: 400px;
+    }
+
+    .poi {
+      overflow-y: auto;
+      width: 320px;
+      height: 400px;
+
+      .list {
+        padding: 8px 20px;
+        border-bottom: 1px solid #e8e8e8;
+        position: relative;
+
+        .name {
+          font-size: 14px;
+          color: #000;
+        }
+
+        .name,
+        .address {
+          line-height: 20px;
+        }
+
+        .address {
+          font-size: 12px;
+          color: #666;
+          margin-top: 2px;
+        }
+
+        i {
+          position: absolute;
+          right: 5px;
+          top: 50%;
+          transform: translate(0, -50%);
+          color: #409EFF;
+          border: 1px solid #409EFF;
+          border-radius: 50%;
+        }
+      }
+    }
+  }
+}
+
+::-webkit-scrollbar {
+  width: 8px;
+  background: none;
+}
+
+::-webkit-scrollbar-thumb {
+  background-color: #cfcfcf;
+  border-radius: 50px;
+}
+</style>