vue2引入高德地图-实现自定义搜索框搜索数据

实现效果图:


1.安装高德地图插件

 npm i @amap/amap-jsapi-loader --save-d

2.template模板部分 dialogWrap是自己封装的弹窗组件(根据el-dialog封装的组件)

    <dialogWrap :visible.sync="show_"
                width="800px"
                top="10vh"
                title="地址识别"
                @confirm="getAddress">
      <div class='map-wrap'>
        <div id="container"></div>
        <div class="search-wrap">
          <!-- 搜索框 -->
          <div class="search">
            <el-input placeholder="请输入内容"
                      v-model="address"
                      class="input-with-select"
                      clearable>
              <!-- @input="handleSearch" -->
              <el-button slot="append"
                         icon="el-icon-search"
                         @click="handleSearch"></el-button>
            </el-input>
          </div>
          <!-- 检索结果 -->
          <div v-show="showResultFlag"
               class="search-result">
            <div v-for="(item, index) in searchResult"
                 class="item"
                 :key="index"
                 @click="reverseeocoding(item.location,item.name)">
              <i class="el-icon-search fl mgr10" />
              <div style="overflow:hidden;">
                <div class="title">{{ item.name }}</div>
                <span class="address ellipsis">{{ item.district+item.address }}</span>
              </div>
            </div>
          </div>
        </div>
      </div>
    </dialogWrap>

3.js实现逻辑部分

<script>
  import dialogWrap from "../dialog/dialogWrap";
  import AMapLoader from "@amap/amap-jsapi-loader";
  window._AMapSecurityConfig = {
    securityJsCode: "自己申请的高德的安全秘钥",
  };
  const defaultInfo = {
    addressAll: '', //详细地址
    address: '', //搜索栏的title | 点击地图的街道号
    province: '', // 省
    city: '', // 市
    district: '', // 区
    street: '' // 街道
  }
  export default {
    props: {
      emitName: String,
      show: {
        type: Boolean,
        default: false,
      },
      // 是否只显示到街道
      isToStreet: {
        type: Boolean,
        default: false,
      }
    },
    components: {
      dialogWrap,
    },
    name: 'Map',
    data () {
      return {
        AMap: null,
        map: null,
        zoom: 15,//地图放大缩小的值
        address: '',//搜索地址
        searchResult: [],//自动匹配地址结果
        showResultFlag: false,
        selectInfo: Object.assign({}, defaultInfo),
        showInfo: false,
        lngLat: '',
        location: '',
      }
    },
    computed: {
      show_: {
        get () {
          return this.show
        },
        set (newVal) {
          this.$emit('update:show', newVal)
        },
      },
    },
    watch: {
      show_ (v) {
        if (v) {
          this.address = ''
          this.showResultFlag = false
          this.selectInfo = this.$options.data().selectInfo
          this.initMap()
        }
      }
    },
  
    methods: {
      initMap () {
        AMapLoader.load({
          key: "自己申请的高德的Web端开发者Key", // 申请好的Web端开发者Key,首次调用 load 时必填
          version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
          plugins: [
            "AMap.AutoComplete",
            "AMap.PlaceSearch",
            "AMap.Geocoder",
          ], // 需要使用的的插件列表
        })
          .then((AMap) => {
            this.AMap = AMap
            this.map = new AMap.Map("container", {
              //设置地图容器id
              zoom: 10, //初始化地图级别
              center: [121.473667, 31.230525], //初始化地图中心点位置
            });
            this.auto = new AMap.AutoComplete(this.autoOptions);
            this.placeSearch = new AMap.PlaceSearch({
              map: this.map,
            }); //构造地点查询类
  
            this.map.on("click", (e) => {
              this.showResultFlag = false
              this.reverseeocoding(e.lnglat)
            });
            //添加固定点标记
            let marker1 = new AMap.Marker({
              position: new AMap.LngLat(121.473667, 31.230525), // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
            });
            //添加点标记
            this.map.add(marker1);
          })
          .catch((e) => {
            console.log(e);
          });
      },
      submit () {
        this.showInfo = false
        this.show_ = false
        top.window.$bus.$emit(`get-address-map-data${this.emitName ? '-' + this.emitName : ''}`, JSON.parse(JSON.stringify(this.selectInfo)))
      },
      handleSearch () {
        let self = this
        if (this.address != null) {
          this.auto.search(this.address, function (status, res) {
            console.log(status, res);
            // 查询成功时,res返回对应匹配的POI信息
            if (res && res.tips) {
              self.searchResult = [...res.tips]
              if (self.searchResult.length > 0) {
                self.showResultFlag = true
              } else {
                self.showResultFlag = false
              }
            } else {
              self.showResultFlag = false
            }
          });
          this.map.setZoom(16, true, 1);
        }
      },
  
      /** 逆地址解析
       * @param {Object}  point 经纬度
       * @param {String}  title 搜索栏下拉数据展示的title名称
       */
      reverseeocoding (point, title) {
        console.log(point);
        this.map.clearMap() //清除地图上所有覆盖物point
        let marker = new this.AMap.Marker({
          position: new this.AMap.LngLat(point.lng, point.lat),
        });
        this.map.add(marker);//添加点标记
  
        // key是高德"web服务"的key
        let params = {
          key: '高德"web服务"的key', //!!!一定要申请的是“web服务”的key哈 不然会提示你无效的
          location: point.lng + "," + point.lat,
        }
        window
          .$axios({
            //这个接口本地调用要在vue.config.js 配置一下代理支持跨域 或者让后端做个方向代理的处理我们直接拿后端返回的接口
            url: "https://restapi.amap.com/v3/geocode/regeo", 
            method: "get",
            data: params,
            params
          })
          .then(res => {
            let data = res.data
            if (data) {
              let { addressComponent } = data.regeocode
              let city = addressComponent.city.length != 0 ? addressComponent.city : addressComponent.province;//城市是省直辖县时返回为空 就直接显示省
              let address = title ? title : addressComponent.streetNumber.street + addressComponent.streetNumber.number //街道+门牌号
              let addString = addressComponent.province + city + addressComponent.district + addressComponent.township
              this.selectInfo = {
                addressAll: title ? addString + title : addString + address,
                address: address,
                province: addressComponent.province,
                city: city,
                district: addressComponent.district,
                street: addressComponent.township,
              }
              this.showInfo = true
              this.lngLat = `${point.lng},${point.lat}`
              this.location = `${this.selectInfo.province},${this.selectInfo.city},${this.selectInfo.district},${this.selectInfo.street}`
              if (!this.isToStreet) this.location = this.location + ',' + address
            }
          });
      },
      getAddress () {
        this.show_ = false
        top.window.$bus.$emit(`get-address-map-data${this.emitName ? '-' + this.emitName : ''}`, JSON.parse(JSON.stringify(this.selectInfo)))
      }
    },
    mounted () {
      let self = this;
      document.addEventListener("keyup", function (e) {
        if (e.keyCode == 13 ) {
          self.handleSearch();
        }
      });
    }
  }
  </script>

4.style部分

<style lang="scss" scoped>
::v-deep .map-wrap {
  position: relative;
  .search {
    width: 410px;
    margin: 16px 0 0 16px;
  }
  .search-result {
    width: 350px;
    margin-left: 16px;
    padding: 10px 0;
    margin-top: 5px;
    background: #fff;
    max-height: 300px;
    overflow-y: auto;
    .item {
      padding: 4px 12px;
      &:hover {
        background: #f5f7fa;
      }
      i.el-icon-search {
        margin-top: 3px;
        font-size: 14px;
      }
      .mgr10 {
        margin-right: 10px;
      }
      .title {
        text-overflow: ellipsis;
        overflow: hidden;
        font-size: 14px;
        padding-bottom: 4px;
      }
      .address {
        line-height: 1;
        font-size: 12px;
        color: #b4b4b4;
        margin-bottom: 5px;
      }
    }
  }
  .bm-view {
    height: 400px;

    .map {
      width: 100%;
      height: 100%;
    }
  }
  .search-wrap {
    position: absolute;
    top: 0;
    left: 0;
  }
  .input-with-select {
    width: 410px;
    .el-input__inner:focus {
      border-color: #d1d5dc;
    }
  }
}
::v-deep .BMap_noprint {
  &.anchorTL {
    top: 16px !important;
    right: 16px !important;
  }
}
::v-deep .BMap_cpyCtrl {
  display: none;
}
::v-deep .anchorBL {
  display: none;
}
::v-deep .el-input-group__append,
.el-input-group__prepend {
  background-color: #3788ee;
  .el-icon-search {
    color: #fff;
    font-weight: 600;
    font-size: 16px;
  }
}
#container {
  width: 750px;
  height: 400px;
}
</style>

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值