vue 使用高德地图制作一个搜索,地图选址的组件

效果展示

效果展示

引入高德地图

    <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=你的key去高德申请很快&plugin=AMap.MouseTool,Amap.PlaceSearch,Amap.Geocoder"></script>

子组件,上完整代码

  1. dom中basic-dialog是我们自己封装的弹窗组件,可以改为自己的弹窗组件 如element的el-dialog
  2. 组件的回显通过show方法传入一个对象包含经纬度和地址名称
  3. 需要子组件emit给父组件的对象中包含什么字段可以自己组装通过submit方法传出去
<template>
  <basic-dialog title="选择位置" :visible="visible" width="55%" @close="close" custom-class="sm-padding-dialog">
    <div class="top-search">
      <el-input v-model="searchInput" placeholder="请输入内容" class="search-input"/>
      <el-button type="primary" @click="searchAddress">搜索</el-button>
    </div>
    <div ref="map" class="map"/>
    <div id="panel"/>
    <span slot="footer" class="dialog-footer">
      <el-button @click="close">取 消</el-button>
      <el-button type="primary" @click="submit">确 定</el-button>
    </span>
  </basic-dialog>
</template>

<script>

// var zoom = 16;
export default {
  name: 'MapChoose',
  data() {
    return {
      // dialog
      visible: false,
      modal: {},
      id: '',
      // map
      map: null,
      mouseTool: null,
      polygon: null,
      markers: null,
      placeSearch: null,
      searchInput: '',
      temporaryObj: {} // 点击之后暂存数据
    };
  },
  methods: {
    // open事件
    show(row) {
      this.visible = true;
      if (row) {
        this.modal = row;
      }
      console.log(this.modal, 'this.modal');
      this.initMap();
    },
    // 初始化地图
    initMap() {
      this.$nextTick(() => {
        const that = this;
        // 地图初始化
        // 设置中心点
        let center = '';
        if (this.modal.location) center = this.modal.location.split(',');
        this.map = new AMap.Map(this.$refs.map, {
          resizeEnable: true,
          center,
          zoom: 16
        });
        // 建立地图搜索服务
        AMap.service(['AMap.PlaceSearch'], () => {
          // 构造地点查询类
          this.placeSearch = new AMap.PlaceSearch({
            pageSize: 5, // 单页显示结果条数
            pageIndex: 1, // 页码
            citylimit: false, // 是否强制限制在设置的城市内搜索
            map: this.map, // 展现结果的地图实例
            panel: 'panel', // 结果列表将在此容器中进行展示。
            autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
            renderStyle: 'default'
          });
        });
        // 搜索出来的地址列表增加点击事件,点击之后赋值
        const onComplete = (row) => {
          console.log(row);
          const { data } = row;
          this.temporaryObj.location = data.location.lng + ',' + data.location.lat;
          this.temporaryObj.address = data.address + '-' + data.name;
          if (this.markers) this.map.remove(this.markers);
        };
        AMap.event.addListener(this.placeSearch, 'listElementClick', onComplete);
        // 添加工具栏
        this.map.plugin(['AMap.ToolBar', 'AMap.Scale'], () => {
          // 工具条
          const toolbar = new AMap.ToolBar();
          // 比例尺
          const scale = new AMap.Scale();
          this.map.addControl(toolbar);
          this.map.addControl(scale);
        });
        // 回显已有marker
        if (this.modal && this.modal.location) {
          const location = this.modal.location.split(',');
          this.markers = new AMap.Marker({
            position: new AMap.LngLat(location[0], location[1]),
            title: this.modal.name
          });
          this.markers.setMap(this.map);
        }
        // 地图点击标点
        this.map.on('click', e => {
          const lng = e.lnglat.lng;
          const lat = e.lnglat.lat;
          // 点击之后获得经纬度,根据经纬度通过反编译获得详细地址
          AMap.plugin('AMap.Geocoder', () => {
            const geocoder = new AMap.Geocoder({
              // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode
              city: ''
            });
            const lngLat = [e.lnglat.lng, e.lnglat.lat];
            geocoder.getAddress(lngLat, (status, result) => {
              if (status === 'complete' && result.info === 'OK') {
                // result为对应的地理位置详细信息
                that.temporaryObj.location = lng + ',' + lat;
                if (that.markers) that.map.remove(that.markers);
                that.markers = new AMap.Marker({
                  position: new AMap.LngLat(lng, lat)
                });
                that.markers.setMap(that.map);
                that.temporaryObj.address = result.regeocode.formattedAddress;
                that.temporaryObj.name = '';
                openInfo(result.regeocode.formattedAddress, lngLat);
              }
            });
          });
        });
        /**
         * 打开marker信息窗体
         * @param add 地址
         * @param lngLat 经纬度数组
         */
        const openInfo = (add, lngLat) => {
          // 构建信息窗体中显示的内容
          const info = [];
          info.push("<div class='input-card content-window-card'>" + add + '</div>');
          const infoWindow = new AMap.InfoWindow({
            content: info.join(''), // 使用默认信息窗体框样式,显示信息内容
            offset: new AMap.Pixel(0, -45)
          });
          infoWindow.open(that.map, lngLat);
        };
      });
    },
    // 搜索服务
    searchAddress() {
      this.placeSearch.search(this.searchInput);
    },
    // submit事件
    submit() {
      console.log(this.modal, 'ssss');
      Object.assign(this.modal, this.temporaryObj);
      this.$emit('mapOk', this.modal);
      this.close();
    },
    // close事件
    close() {
      // 销毁地图
      this.temporaryObj = {};
      if (this.map) this.map.destroy();
      if (this.markers) this.markers = null;
      this.visible = false;
    }
  }
};
</script>

<style lang="scss" scoped>
#panel {
  position: absolute;
  background-color: white;
  max-height: 90%;
  overflow-y: auto;
  top: 120px;
  right: 50px;
  width: 320px;
}
.top-search{
  display: flex;
  flex-wrap: nowrap;
  justify-content: flex-start;
  position: absolute;
  top: 80px;
  right: 50px;
  z-index: 1;
  width: 320px;
  .search-input{
    margin-right: 10px;
  }
}
.map {
  width: 100%;
  height: 70vh;
}

.button-group {
  position: absolute;
  right: 12px;
  bottom: 65px;
  z-index: 1;

  .tips {
    color: red;
    font-size: 12px;
    line-height: 18px;
  }
}

#myPageTop {
  padding: 8px;
  position: absolute;
  top: 60px;
  right: 50px;
  background: #fff;
  border: 1px solid #cccccc;
}
</style>

父组件使用,组件为全局注册,表单中的样式自己写

// 打开的方法使用ref调用子组件中的方法打开弹窗
 this.$refs.mapChoose.show(this.clickRow); // 打开地图
 此处的this.clickRow是将下面的对象传给子组件,子组件将选择的点回显到地图上,如果是第一次打开的话 就将里面的值置空就行
 
{
	address: "四川省成都市青羊区西御河街道东华正街人民中路一段5号院"
	contentUEditor: ""
	location: "104.068455,30.660047"
	name: ""
	parentCode: "0"
	parentName: "无上级"
	reseauLeaderUserinfoCode: ""
	reseauType: ""
	reseauUserinfoCodesValue: Array(0)
	shortName: ""
}

 
 // 使用
 <mapSelectLocation ref="mapChoose" @mapOk="mapOk"/>
 
// 地址赋值
 mapOk(val) {
    if (val) {
      this.modelForm.address = val.address;
      this.modelForm.location = val.location;
    } else {
      this.modelForm.address = '';
      this.modelForm.location = '';
    }
  }

打印出来val的值看看

address: "四川省成都市青羊区西御河街道东华正街人民中路一段5号院"
contentUEditor: ""
location: "104.068455,30.660047"
name: ""
parentCode: "0"
parentName: "无上级"
reseauLeaderUserinfoCode: ""
reseauType: ""
reseauUserinfoCodesValue: Array(0)
shortName: ""
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值