vue+vantUI+高德地图构成的地图选址组件

效果图如下:
主要功能:搜索,分页,距离显示,选择地址,移动地图查询附近相关地点。
在这里插入图片描述
1.首先在index.html引入高德地图的js;

 <!-- 高德地图的引用 -->
  <script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=你的key">
  </script>
  <!--引入UI组件库(1.0版本) -->
  <script src="//webapi.amap.com/ui/1.0/main.js"></script>

2.在vue项目中配置AMap,AMapUI,在项目配置里面加上如下代码:

//方式一
externals: {
    'AMap': 'AMap',
    'AMapUI': 'AMapUI'
  },

//方式二
configureWebpack: {
    externals: {
      AMap: "window.AMap",
      AMapUI: "window.AMapUI"
    }
  },

(1)如果是用webpack自行定义配置的;
在这里插入图片描述
(2)如果用的是vue-cli3脚手架配置的:
在这里插入图片描述
3.开始写代码了,html部分如下:

  <van-popup
    class="address-map-wrap"
    v-model="value"
    position="right"
    :style="{ width: '100%', height: '100%' }"
    :overlay="false"
    @open="onOpenMap"
  >
    <div class="mymapM">
      <!--loading-->
      <div v-if="loading" class="loading">
        <van-loading type="spinner" />
      </div>
      <div class="current-location" @click="goBackOrign()">
        <van-icon name="aim" />
      </div>
      <div class="header">
        <dt-header
          :title="header.title"
          :left-text="header.leftText"
          :right-text="header.rightText"
          :left-arrow="header.leftArrow"
          @click-left="onClickLeft"
          @click-right="onConfirmChoose"
        />
      </div>

      <div class="con-map">
        <!--地图-->
        <div class="mapbox">
          <div class="map" id="container"></div>
          <div class="sign"></div>
        </div>
      </div>
      <div class="con-box">
        <!-- 搜索 -->
        <van-search
          v-model="search_key"
          :show-action="showCancelBtn"
          placeholder="请输入搜索关键词"
          @input="keyInputSearch"
          @cancel="onCancel"
        />
        <!--地址列表-->
        <div class="Hlist-box">
          <van-list
            v-model="loadingList"
            :finished="finished"
            finished-text="没有更多了"
            @load="onLoad"
            :offset="200"
            :immediate-check="false"
          >
            <ul class="van-clearfix">
              <li
                v-for="(item, index) in lists"
                :key="index"
                @click="onAddressLi(item)"
              >
                <div>
                  <span>{{ item.name }}</span>
                  <p>{{ item.distance }}-{{ item.address }}</p>
                </div>
                <b v-if="item.isChecked">
                  <van-icon color="#04BE02" name="success" />
                </b>
              </li>
            </ul>
          </van-list>
        </div>
      </div>
    </div>
  </van-popup>

4.样式如下,用的是less:

 .mymapM {
    .header {
      position: fixed;
      z-index: 99999;
      width: 100%;
    }
    .con-map {
      height: 300px;
      width: 100%;
      .mapbox {
        position: fixed;
        z-index: 111;
        width: 100%;
        height: 300px;
        .map {
          width: 100%;
          height: 300px;
        }
      }
    }
    .con-box {
      height: calc(~"100vh - @{mapHeight}");
      max-height: calc(~"100vh - @{mapHeight}");
      overflow-y: auto;
      .van-search {
        position: fixed;
        width: 100%;
      }
      .Hlist-box {
        width: 100%;
        padding: 60px 0 10px 0;
        background: #fff;
        border-radius: 5px;
        li {
          padding: 10px 15px;
          border-bottom: 1px solid #eee;
          display: flex;
          b {
            display: inline-block;
            i {
              margin: 10px 10px 0 0;
            }
          }
          div {
            width: 100%;
          }
          span {
            white-space: nowrap;
            text-overflow: ellipsis;
            overflow: hidden;
            font-size: 14px;
            display: inline-block;
            width: 90%;
          }
          p {
            margin-top: 0px;
            color: #a6a6a6;
            // white-space: nowrap;
            // text-overflow: ellipsis;
            // overflow: hidden;
            font-size: 12px;
            width: 90%;
          }
        }
      }
    }
  }
  .no-search-content {
    text-align: center;
    p {
      font-size: 12px;
      padding-bottom: 10px;
    }
  }
  .current-location {
    position: fixed;
    z-index: 100000;
    top: 250px;
    right: 10px;
    font-size: 25px;
    background: #fff;
    border-radius: 100px;
    height: 40px;
    width: 40px;
    line-height: 45px;
    text-align: center;
  }

  .loading {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 99999999;
    //   width: 100%;
    //   height: 100%;
    //   background-color: rgba(0, 0, 0, 0.3);
    .van-loading {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
      z-index: 99999999;
      color: green;
    }
  }

5.方法代码如下:


<script> 
import {
  Search,
  Popup, 
  Icon, 
  Loading,
  List,
} from "vant";
import AMap from "AMap";
import AMapUI from "AMapUI";
import dtHeader from "@/components/dtHeader";
import { dtBack, dtLocationInfo, getDevice } from "@/config/bridging";
export default {
  name: "mapAddress",
  components: {
    [Loading.name]: Loading,
    [Search.name]: Search,
    [dtHeader.name]: dtHeader,
    [Popup.name]: Popup, 
    [Icon.name]: Icon, 
    [List.name]: List,
  },
  props: {
    value: Boolean,
    currentLocation: Array,
    currentAdCode: String, //当前定位所在的AdCode北京
  },
  data() {
    return {
      header: {
        title: "调查地点",
        leftText: "",
        rightText: "确定",
        leftArrow: true,
      },
      loadingList: false,
      finished: false,
      pageNearNum: 1,
      pageKeyNum: 1,
      originCenter: [116.396574, 39.992706], //初始的地址
      center: [116.396574, 39.992706], //默认的 经度+纬度北京
      search_key: "", //搜索值
      lists: [], //地点列表
      marker: "",
      map: "",
      loading: false,
      checkedAddress: "", //选中的地址
      showCancelBtn: false, //取消按钮的显示问题
    };
  },
  watch: { 
    search_key(newv, oldv) {
      if (newv == "") {
        this.lists = [];
        this.showCancelBtn = false;
        this.adMap();
      }
    },
  },
  created() {},
  mounted() {},
  methods: {
    onClickLeft() {
      this.$emit("onClickLeft", false);
    },
    onConfirmChoose() {
      if (this.checkedAddress) {
        this.$emit("onClickLeft", false);
        this.$emit("onChooseAddress", this.checkedAddress);
      } else {
        this.$toast.fail("请先选择地址");
        return;
      }
    },
    //用的popup弹框
    onOpenMap() {
      this.$nextTick(() => { 
        this.lists = [];
        this.checkedAddress = "";
        this.pageNearNum = 1;
        this.pageKeyNum = 1;
        this.getCurrentLocation(); //获取当前位置,app内使用原生获取当前定位
      });
    },
    //分页加载
    onLoad() {
      if (this.search_key) {
        this.loadingList = true;
        this.keySearch(++this.pageKeyNum);
      } else {
        this.loadingList = true;
        this.centerSearch(++this.pageNearNum); 
      }
    },
    //初次选择位置的时候,获取当前地址的经纬度
    getCurrentLocation() {
      if (this.currentLocation.length > 0 && this.currentAdCode) {
        this.center = this.currentLocation; // 当前定位
        this.originCenter = this.currentLocation; //保存最原始的位置
        this.adMap(); //初始化地图
      } else {
        dtLocationInfo((res, a, b) => {
          console.log("返回的地址信息:", res, a, b);
          var device = getDevice();
          if (device == "android") {
            var data = JSON.parse(res);
            this.center = [data.longitude, data.latitude];
            this.originCenter = [data.longitude, data.latitude];
            this.currentAdCode = data.adCode;
          } else if (device == "ios" || device == "iPhoneX") {
            if (res) {
              this.center = [a.longitude, a.latitude];
              this.originCenter = [a.longitude, a.latitude];
              this.currentAdCode = a.adCode;
            } else {
              this.$toast.fail(b);
            }
          } else {
            throw new Error("can't know device type!");
          } 
          this.adMap(); //初始化地图
        });
      }
    },

    //创建地图
    adMap() {
      this.loading = true;
      var map = new AMap.Map("container", {
        zoom: 13, //缩放级别
        center: this.center, //设置地图中心点
        resizeEnable: true,
      });
      var currentCenter = map.getCenter(); //此方法是获取当前地图的中心点
      this.center = [currentCenter.lng, currentCenter.lat]; //将获取到的中心点的纬度经度赋值给data的center

      this.map = map;
      //创建当前标志;
      var currentMarker = new AMap.CircleMarker({
        map: map,
        center: this.originCenter, // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
        radius: 8,
        strokeColor: "white",
        strokeWeight: 2,
        strokeOpacity: 1,
        fillColor: "#4c95fb",
        fillOpacity: 1,
        zIndex: 10,
        bubble: true,
        cursor: "pointer",
      });

      //创建位置标记
      this.marker = new AMap.Marker({
        map: map,
        position: new AMap.LngLat(currentCenter.lng, currentCenter.lat), // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
      });

      if (this.search_key) {
        this.lists = [];
        this.keySearch(1); //根据关键字搜索
      } else {
        this.lists = [];
        this.centerSearch(1); //根据地图中心点查附近地点,此方法在下方
      }

      //监听地图移动事件,并在移动结束后获取地图中心点并更新地点列表
      var moveendFun = (e) => {
      //没有关键字的时候,移动地图,数据及时刷新,更新地图,否则中心点不变
        if (!this.search_key) {
          currentCenter = map.getCenter(); // 获取地图中心点
          this.center = [currentCenter.lng, currentCenter.lat];
          this.marker.setPosition([currentCenter.lng, currentCenter.lat]); //更新标记的位置
        }
      };
      //更新数据
      var centerSearch = () => {
        if (!this.search_key) {
          this.loading = true;
          this.checkedAddress = "";
          this.lists = [];
          this.centerSearch(1);
        }
      };

      // 绑定事件移动地图事件
      map.on("touchmove", moveendFun); //触摸移动进行中时触发事件,仅适用移动设备
      map.on("touchend", centerSearch); //触摸结束时触发事件,仅适用移动设备,更新数据
    },

    //根据地图中心点查附近地
    centerSearch(pageNum) {
      AMap.service(["AMap.PlaceSearch"], () => {
        //构造地点查询类

        var placeSearch = new AMap.PlaceSearch({
          type:
            "汽车服务|汽车销售|汽车维修|摩托车服务|餐饮服务|购物服务|生活服务|体育休闲服务|医疗保健服务|住宿服务|风景名胜|商务住宅|政府机构及社会团体|科教文化服务|交通设施服务|金融保险服务|公司企业|道路附属设施|地名地址信息", // 兴趣点类别

          pageSize: 20, // 单页显示结果条数
          pageIndex: parseInt(pageNum), // 页码
          city: "全国", // 兴趣点城市
          extensions: "all",
          autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
        });
        var geometryUtil = AMap.GeometryUtil;
        //根据地图中心点查附近地点
        placeSearch.searchNearBy(
          this.search_key,
          [this.center[0], this.center[1]],
          10000,
          (status, result) => {
            if (status == "complete") {
              console.log("searchNearBy--complete---:", result);
              this.lists = this.lists.concat(result.poiList.pois);
              this.lists.length < result.poiList.count
                ? (this.finished = false)
                : (this.finished = true);

              this.lists = this.lists.map((item) => {
                let distance = geometryUtil.distance(this.originCenter, [
                  item.location.lng,
                  item.location.lat,
                ]);
                item.distance =
                  parseInt(distance) > 1000
                    ? parseFloat(distance / 1000).toFixed(2) + "km"
                    : parseInt(distance) + "m";
                return item;
              });

              this.lists[0].isChecked = true;
              this.checkedAddress = this.lists[0];
              this.loading = false;
              this.loadingList = false;
            } else {
              console.log("searchNearBy-notcomplete------:", result);
              // this.loadingList = false;
              this.finished = true;
              this.loading = false;
            }
          }
        );
      });
    },

    keyInputSearch() {
      this.lists = [];
      this.keySearch(1);
    },
    //关键字搜索
    keySearch(pageNum) {
      this.loading = true;
      this.showCancelBtn = true;

      if (this.search_key) {
        AMap.service(["AMap.PlaceSearch"], () => {
          //构造地点查询类
          var placeSearch = new AMap.PlaceSearch({
            type:
              "汽车服务|汽车销售|汽车维修|摩托车服务|餐饮服务|购物服务|生活服务|体育休闲服务|医疗保健服务|住宿服务|风景名胜|商务住宅|政府机构及社会团体|科教文化服务|交通设施服务|金融保险服务|公司企业|道路附属设施|地名地址信息|公共设施", // 兴趣点类别
            pageSize: 20, // 单页显示结果条数
            pageIndex: pageNum, // 页码
            city: this.currentAdCode, // 兴趣点城市,默认北京
            extensions: "all",
            citylimit: false, //是否强制限制在设置的城市内搜索
            autoFitView: true, // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
          });
          var geometryUtil = AMap.GeometryUtil;
          //关键字查询
          placeSearch.search(this.search_key, (status, result) => {
            if (status == "complete") {
              console.log("search:", result);
              if (result.poiList.count === 0) {
                this.loading = false;
                this.finished = true;
              } else {
                this.lists = this.lists.concat(result.poiList.pois);

                this.lists.length < result.poiList.count
                  ? (this.finished = false)
                  : (this.finished = true);
                this.lists = this.lists.map((item) => {
                  if (
                    item.location.lng == this.currentLocation[0] &&
                    item.location.lat == this.currentLocation[1]
                  ) {
                    item.isChecked = true;
                    this.checkedAddress = item;
                  } else {
                    item.isChecked = false;
                  }
                  let distance = geometryUtil.distance(this.originCenter, [
                    item.location.lng,
                    item.location.lat,
                  ]);
                  item.distance =
                    parseInt(distance) > 1000
                      ? parseFloat(distance / 1000).toFixed(2) + "km"
                      : parseInt(distance) + "m";
                  return item;
                });

                this.loading = false;
                this.loadingList = false;
              }
            } else {
              // this.lists = [];
              this.loading = false;
              this.finished = true;
            }
          });
        });
      }
    },
    onAddressLi(e) {
      this.checkedAddress = e;
      this.map.setCenter([e.location.lng, e.location.lat]); //更新地图中心
      this.marker.setPosition([e.location.lng, e.location.lat]); //更新标记的位置
      this.lists = this.lists.map((item) => {
        if (item.id == e.id) {
          item.isChecked = true;
        } else {
          item.isChecked = false;
        }
        return item;
      });
    },
    onCancel() {
      this.search_key = "";
      this.checkedAddress = "";
      this.pageNearNum = 1;
      this.pageKeyNum = 1;
      this.map.setCenter(this.originCenter);
      this.marker.setPosition(this.originCenter); //更新标记的位置
    },
    //回到当前位置
    goBackOrign() {
      this.map.setCenter(this.originCenter);
    },
  },
};
</script>
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
Vue项目中使用Vant组件库进行后台管理时,如果需要实现地图选点功能,可以借助第三方地图API,如高德地图或百度地图等。 首先,需要在项目中引入地图相关的API库文件,并按照API提供的文档进行初始化设置。可以将API引入到Vue组件中,或者在index.html中直接引入。 接下来,在需要显示地图Vue组件中,使用Vant提供的组件构建地图的容器,如`van-cell`或`van-field`等。通过绑定对应的值,设置地图的宽度、高度等样式,并确保容器元素在页面中可见。 然后,在Vue组件的`mounted`生命周期钩子函数中,使用第三方地图API创建地图实例。根据API提供的方法,可以设置地图的中心点、缩放级别等属性,使地图初始显示在指定的位置。 在地图上实现选点功能,可以使用API提供的方法来监听地图上的点击事件。当用户点击地图时,可以通过相关回调函数获取点击的经纬度信息,并将此坐标保存到Vue组件的数据模型中。 为了在地图上显示已选定的位置,可以使用API提供的方法,根据保存的坐标信息,在地图上进行标记或绘制。标记可以是一个图标或者一个自定义的标记样式,用以表示用户选择的地点位置。 最后,为了让用户能够选择并确认地点,可以在页面中添加相应的按钮或输入框等交互元素。当用户点击确认时,可以根据已选的地点坐标进行相应的处理,如保存到数据库、发送请求等。 总的来说,通过结合VueVant组件库,以及第三方地图API,可以较方便地实现后台管理系统中的地图选点功能,提供给用户更好的地图使用体验。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值