美文网首页
vue 使用百度地图:搜索定点

vue 使用百度地图:搜索定点

作者: 牛会骑自行车 | 来源:发表于2022-03-02 16:41 被阅读0次

    需求:
    1.以某一点为圆心,半径5000米以内的地方进行标注;
    2.点击选择定位,添加覆盖物,并解析地址;
    3.通过搜索进行定位:↑↓键进行选择Enter键确定,也可以点击选择,并添加覆盖物。

    效果图 ↓

    官网地址:
    https://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-placeapi

    这次的需求是,圆心五公里之内的地方,需要可以搜索定点。根据文档,需要用到的api是
    https://api.map.baidu.com/place/v2/search?query=银行&location=39.915,116.404&radius=2000&output=xml&ak=您的密钥
    具体参数看上面的网址就成~~
    在解析地址时,可能会出现跨域问题,所以我们还需要安装一个vue-jsonp。

    安装 ↓

    npm install vue-jsonp --s
    

    main.js ↓

    import {VueJsonp} from "vue-jsonp"; 
    Vue.use(VueJsonp);
    

    在utils中创建文件loadMap.js ↓

    export default function loadBMap(ak) {
        return new Promise(function(resolve, reject) {
          if (typeof BMap !== 'undefined') {
            resolve(BMap)
            return true
          }
          window.onBMapCallback = function() {
            resolve(BMap)
          }
          let script = document.createElement('script')
          script.type = 'text/javascript'
          script.src =
            'http://api.map.baidu.com/api?v=2.0&ak=' + ak + '&callback=onBMapCallback'
          script.onerror = reject
          document.head.appendChild(script)
        })
      }
    

    准备工作就完成啦~~~~

    正式代码片段

    html ↓

        <div class="baidu-map-container">
          <div id="tips-container">
            当前定位地址:
            <el-input
              clearable
              v-model="locationTips"
              size="mini"
              @input="onInputLocation"
              @blur="dispearAddressDrop"
              @keyup.native="keydownChangeLocation"
              @focus="onFocusLocation"
            ></el-input>
            <!-- ↓ 为搜索时出现的下拉框 -->
            <div class="drop-container" v-if="addressSearchDropShow">
              <div
                class="loop-address-search"
                v-for="(address, idx) in addressSearchList"
                :key="address.uid"
                :class="addressNum === idx ? 'active-address' : ''"
                @click="handleChooseAddress(idx)"
              >
                <i class="el-icon-search icon"></i>
                <p class="name">{{ address.name }}</p>
                <p class="address">{{ address.city + address.area }}</p>
              </div>
            </div>
          </div>
          <!-- ↓ 地图容器 -->
          <div id="baidu-map-container"></div>
        </div>
    

    css ↓ (首先要确保容器有足够的宽高)

    .baidu-map-container {
      height: 480px;
      position: relative;
      #baidu-map-container {
        width: 100%;
        height: 100%;
        position: absolute;
        left: 0;
        top: 0;
      }
      #tips-container {
        z-index: 1;
        position: absolute;
        top: 10px;
        left: 10px;
        padding: 0px 7px;
        min-width: 400px;
        height: 70px;
        line-height: 35px;
        background: #fff;
        box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
        border-bottom: 1px solid lightgrey;
        font-size: 12px;
        .drop-container {
          min-width: 400px;
          max-height: 400px;
          overflow: scroll;
          overflow-y: auto;
          overflow-x: hidden;
    
          position: absolute;
          left: 0;
          background: white;
          .loop-address-search {
            padding: 0 7px;
            display: flex;
            align-items: center;
            cursor: pointer;
            .icon,
            .name {
              margin-right: 10px;
            }
            .icon {
              line-height: 20px;
            }
            .address {
              color: #999999;
            }
          }
          .loop-address-search:hover {
            background: rgba(0, 0, 0, 0.1);
          }
          .active-address {
            background: rgba(0, 0, 0, 0.1);
          }
        }
        .drop-container::-webkit-scrollbar {
          display: none;
        }
      }
    }
    

    script ↓

      // 引入写好的使用百度地图的方法
      import loadMap from "@/components/BaiduMap/loadMap";
    
      data() {
        return {
          addressSearchDropShow: false,
          addressNum: -1, // 控制地址搜索下拉框是否选中的变量
          addressSearchList: [], // 搜索下拉框的数组
          
          locationTips: "", 
          ifHasSearchAddress: false,
          // 不知道该怎么备注了。。。。都是语义化自己理解吧
          currentSearchAddressInfo: {
            lng: "",
            lat: "",
          },
          // 中心点坐标
          center: {
            lng: "119.587727",
            lat: "39.961482",
          },
        };
      },
      methods: {
        // 下拉框消失
        dispearAddressDrop() {
          // 设置定时器原因:
          // 当点击下拉框中的任意一条时,会先执行el-input的blur方法
          // 即,下拉框先消失,后面的语句都执行不了啦
          setTimeout(() => {
            this.addressNum = -1;
            this.addressSearchDropShow = false;
          }, 100);
        },
        // 选中某条数据时,将选中的地址放输入框里,并保存经纬度
        handleChooseAddress(idx) {
          let addressInfo = this.addressSearchList[idx];
          // 当选择了一个地址后保存一个变量,地图添加覆盖物时会有用
          this.ifHasSearchAddress = true;
          // 文字入框 获取经纬度
          this.locationTips = addressInfo.name;
          this.currentSearchAddressInfo = { ...addressInfo.location };
          // 获取到选中的经纬度后需要重新加载地图
          this.initBaiduMap();
          this.dispearAddressDrop();
        },
        onFocusLocation(e) {
          if (e.target.value) {
            this.addressNum = -1;
            this.addressSearchDropShow = true;
          }
        },
        keydownChangeLocation(e) {
          if (e.keyCode === 40) {
            // ↓
            if (this.addressNum < this.addressSearchList.length - 1) {
              this.addressNum++;
            } else {
              this.addressNum = 0;
            }
          }
          if (e.keyCode === 38) {
            // ↑
            if (this.addressNum <= 0) {
              this.addressNum = this.addressSearchList.length - 1;
            } else {
              this.addressNum--;
            }
          }
          if (e.keyCode === 13) {
            // Enter
            this.handleChooseAddress(this.addressNum);
          }
        },
        // 通过输入的文字搜索一定范围内的地址
        onInputLocation(val) {
          this.addressNum = -1;
          this.addressSearchDropShow = true;
          // 获取出现地址的API
          this.$jsonp(
            `https://api.map.baidu.com/place/v2/search?query=${val}&location=${this.center.lat},${this.center.lng}&radius=5000&output=json&ak=你的密钥`
          ).then((res) => {
            this.addressSearchList = res.results;
          });
        },
        initBaiduMap() {
            loadMap("你的密钥")
            .then(() => {
              // 之后在circle中添加点击事件时this指向会发生改变所以先存一个
              let _this = this;
              // 初始化地图
              this.myMap = new BMap.Map("baidu-map-container");
              // 中心点和缩放
              this.myMap.centerAndZoom(
                new BMap.Point(this.center.lng, this.center.lat),
                13
              );
              // 地图可以使用鼠标滚轮进行缩小放大
              this.myMap.enableScrollWheelZoom();
    
              let geoc = new BMap.Geocoder();
              // 设置规定范围的圆圈
              let circle = new BMap.Circle(
                new BMap.Point(this.center.lng, this.center.lat),
                5000,
                {
                  strokeColor: "green",
                  strokeWeight: 6,
                  strokeOpacity: 0.5,
                }
              );
              // 添加覆盖物 规定范围的圈儿
              this.myMap.addOverlay(circle);
              // 圆圈儿在之后可能会进行的clearOverlays()时不会被删除
              circle.disableMassClear();
    
              let marker;
              // 选择搜索地址后保存的变量
              if (this.ifHasSearchAddress) {
                marker = new BMap.Marker(
                  new BMap.Point(
                    this.currentSearchAddressInfo.lng,
                    this.currentSearchAddressInfo.lat
                  )
                );
                // 如果有选中的地址则添加marker
                this.myMap.addOverlay(marker);
              }
    
              // 给圈儿内的地图范围添加点击事件
              circle.addEventListener("click", function (e) {
                // 清空下拉框中的数据
                _this.addressSearchList = [];
                // 清空之前的覆盖物
                _this.myMap.clearOverlays();
    
                let point = e.point;
                // 获取点击地点的经纬度
                _this.longitude = point.lng;
                _this.latitude = point.lat;
                // 添加覆盖物
                let markerPoint = new BMap.Marker(
                  new BMap.Point(point.lng, point.lat)
                );
                _this.myMap.addOverlay(markerPoint);
    
                // 将点选的地址信息存入data中
                geoc.getLocation(point, function (rs) {
                  let position = rs.addressComponents;
    
                  _this.locationTips = `${position.province}${position.city}${position.district}${position.street}${position.streetNumber}`;
                });
              });
            })
            .catch((err) => {
              console.log("地图加载失败");
            });
        }
      },
      mounted() {
        this.initBaiduMap();
      },
    

    tada~一个可以点选也可以搜索定点的地图就完成啦

    相关文章

      网友评论

          本文标题:vue 使用百度地图:搜索定点

          本文链接:https://www.haomeiwen.com/subject/lzbdrrtx.html