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

需求:
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~一个可以点选也可以搜索定点的地图就完成啦

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容