vue整合百度地图(关键字检索)

百度地图



一、申请百度地图的密钥

官网入口
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
白名单要为 *
在这里插入图片描述
创建成功
在这里插入图片描述


二、官方示例

示例入口

比较有意思的几个案例
在这里插入图片描述
在这里插入图片描述

三、使用vue整合百度地图步骤说明

3.1 效果图:

在这里插入图片描述
说明:

  1. 搜索检索位置,获取经纬度
  2. 地图标点反解析出经纬度

3.2 方式一 vue脚手架2.0版本引用(不推荐):

  1. 在index.html引入
    在这里插入图片描述
<script async type="text/javascript" src="https://api.map.baidu.com/api?v=3.0&ak=你的ak"></script>
  1. 在 webpack.base.conf.js 添加externals.BMap配置,与entry平级,内容如下
entry: {
  app: ['babel-polyfill', './src/main.js']
},
externals: {
  BMap: 'BMap'
}

说明:vue-cli 3.0+ 的版本已经取消了webpack.conf这些文件了,所以上面的方法就不适用了,而且耗费性能

其实在config里面也可以使用,但是不推荐:
在这里插入图片描述
3. 在组件中引入BMap

3.3 方式二 封装成js引用(推荐做法):

3.3.1 封装loadBMap.js

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

位置:
在这里插入图片描述

3.3.2 在组件中引入封装的loadBMap

import loadBMap from "@/utils/loadBMap.js";

3.3.3 在mounted中调用 loadBMap()

 async mounted() {
    await loadBMap() // 加载引入BMap,封装的js
    this.initMap()//这个是初始化地图的方法,在method中定义
  },

这样组件基本准备完成,可以根据百度官方示例进行编写

四、整合详解(单独地图页面)

4.1、直接上完整代码,代码注释详解

<template>
  <!-- 定义大个盒子 -->
  <div class="app-container">
    <!--使用element ui -->
    <el-form ref="form" :model="form" label-width="110px">
      <!-- 检索框部分   -->
      <el-form-item label="详细地址:" prop="address">
        <el-autocomplete
          v-model="form.address"
          style="width:100%;"
          popper-class="autoAddressClass"
          :fetch-suggestions="querySearchAsync"
          :trigger-on-focus="false"
          placeholder="详细地址"
          clearable
          @select="handleSelect"
        >
        <!-- 双向数据绑定 -->
          <template slot-scope="{ item }">
            <i class="el-icon-search fl mgr10" />
            <div style="overflow:hidden;">
              <div class="title">{{ item.title }}</div>
              <span class="address ellipsis">{{ item.address }}</span>
            </div>
          </template>
        </el-autocomplete>
      </el-form-item>
      <!-- 地图盒子 -->
      <el-form-item label="地图定位:">
        <div id="map-container" style="width:100%;height:500px;" />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="onSubmit">提交</el-button>
        <el-button>取消</el-button>
      </el-form-item>
    </el-form>
  </div>
</template>

<script>
// 引入封装的js
import loadBMap from '@/utils/loadBMap.js'
export default {
  data() {
    return {
      form: {
        address: '', // 详细地址
        addrPoint: { // 详细地址经纬度
          lng: 0,
          lat: 0
        }
      },
      map: '', // 地图实例
      mk: '', // Marker实例
      locationPoint: null
    }
  },
  async mounted() {
    await loadBMap() // 加载引入BMap
    this.initMap()//初始化地图
  },
  methods: {
    // 初始化地图的方法
    initMap() {
      var that = this

      // 1、挂载地图
      this.map = new BMap.Map('map-container', { enableMapClick: false })
      var point = new BMap.Point(113.3324436, 23.1315381)//设置个默认标点
      this.map.centerAndZoom(point, 19)

      // 3、设置图像标注并绑定拖拽标注结束后事件
      this.mk = new BMap.Marker(point, { enableDragging: true })
      this.map.addOverlay(this.mk)
      this.mk.addEventListener('dragend', function(e) {
        that.getAddrByPoint(e.point)
      })

      // 4、添加(右上角)平移缩放控件
      this.map.addControl(new BMap.NavigationControl({ anchor: BMAP_ANCHOR_TOP_RIGHT, type: BMAP_NAVIGATION_CONTROL_SMALL }))

      // 5、添加(左下角)定位控件
      var geolocationControl = new BMap.GeolocationControl({ anchor: BMAP_ANCHOR_BOTTOM_LEFT })
      geolocationControl.addEventListener('locationSuccess', function(e) {
        that.getAddrByPoint(e.point)
      })
      geolocationControl.addEventListener('locationError', function(e) {
        alert(e.message)
      })
      this.map.addControl(geolocationControl)

      // 6、浏览器定位
      this.geolocation()

      // 7、绑定点击地图任意点事件
      this.map.addEventListener('click', function(e) {
        that.getAddrByPoint(e.point)
      })
    },

    // 获取两点间的距离
    getDistancs(pointA, pointB) {
      return this.map.getDistance(pointA, pointB).toFixed(2)
    },
    
    // 浏览器定位函数
    geolocation() {
      var that = this
      var geolocation = new BMap.Geolocation()
      geolocation.getCurrentPosition(function(res) {
        if (this.getStatus() == BMAP_STATUS_SUCCESS) {
          that.getAddrByPoint(res.point)
          that.locationPoint = res.point
        } else {
          alert('failed' + this.getStatus())
          console.log('failed' + this.getStatus())
          that.locationPoint = new BMap.Point(113.3324436, 23.1315381)
        }
      }, { enableHighAccuracy: true })
    },

    // 2、逆地址解析函数
    getAddrByPoint(point) {
      var that = this
      var geco = new BMap.Geocoder()
      geco.getLocation(point, function(res) {
        console.log(res)
        that.mk.setPosition(point)
        that.map.panTo(point)
        that.form.address = res.address
        that.form.addrPoint = point
      })
    },
    // 8-1、地址搜索
    querySearchAsync(str, cb) {
      var options = {
        onSearchComplete: function(res) {
          var s = []
          if (local.getStatus() == BMAP_STATUS_SUCCESS) {
            for (var i = 0; i < res.getCurrentNumPois(); i++) {
              s.push(res.getPoi(i))
            }
            cb(s)
          } else {
            cb(s)
          }
        }
      }
      var local = new BMap.LocalSearch(this.map, options)
      local.search(str)
    },
    // 8-2、选择地址
    handleSelect(item) {
      this.form.address = item.address + item.title
      this.form.addrPoint = item.point
      this.map.clearOverlays()
      this.mk = new BMap.Marker(item.point)
      this.map.addOverlay(this.mk)
      this.map.panTo(item.point)
    },
    //点击确定输出form表单的内容
    onSubmit() {
      console.log(this.form)
    }
  }
}
</script>
<!-- 样式 -->
<style lang="scss" scoped>
  .autoAddressClass{
    li {
      i.el-icon-search {margin-top:11px;}
      .mgr10 {margin-right: 10px;}
      .title {
        text-overflow: ellipsis;
        overflow: hidden;
      }
      .address {
        line-height: 1;
        font-size: 12px;
        color: #b4b4b4;
        margin-bottom: 5px;
      }
    }
  }
</style>

五、地图为子组件,点击触发按钮,展示地图(更常见,详解)

5.1效果图

1、 点击选择,打开地图的组件
在这里插入图片描述
2、检索功能,也能在地图自己标点
在这里插入图片描述
3、提示信息
在这里插入图片描述
3、回显数据,地图组件将数据传输给父组件,父组件取
在这里插入图片描述

第一步,一样先引入封装好的js文件

5.2 在主页面引入js,点击按钮调用地图初始化方法

引入js

import loadBMap from '@/utils/loadBMap.js'

钩子方法加载


created() {
    // 地图
    loadBMap()// 加载引入BMap
  }

引入地图组件

//说明@afterSelectPosition="afterSelectPosition"这个是绑定的方法
//用于子组件(地图)给父组件通信(传值)
<selectPosition ref="selectPositionWin" @afterSelectPosition="afterSelectPosition" />

在主页面点击选择,展开地图
在这里插入图片描述
点击触发地图的方法

selectPosition() {
     // 调用子组件(地图)的初始化方法
     this.$refs.selectPositionWin.myMehod()
},

5.3完整的子组件地图代码(dialog包裹)

要点说明

  • 使用父组件触发子组件地图,子组件(地图)必须使用 $nextTick 方法,不会第一次会看不到地图,第二次才有
  • 子组件向父组件通信是采用$emit方法
  • 小编使用的是vue+element+百度地图

$nextTick说明:


Vue.nectTick()介绍: 是在下次DOM更新循环结束之后执行延迟回调,在修改数据之后使用$nextTick,则可以在回调中获取更新后的DOM(dom的改变是发生在nextTick()之后),这个方法作用是当数据被修改后使用这个方法,会回调获取更新后的dom再render出来


Vue.nextTick()作用:在下次dom更新循环结束之后,执行延迟回调。在修改数据之后立即使用这个方法,获得更新后的dom

<template>
  <!--  dialogShow绑定对话框是否展示,默认为false-->
  <el-dialog :visible.sync="dialogShow" :title="dialogTitle" :close-on-click-modal="false" append-to-body top="5vh"
             width="900px" height="400px">
    <!-- 大盒子-->
    <div class="app-container">
      <!--   element ui   -->
      <el-form ref="form" :model="form" label-width="110px">
        <!-- 检索框-->
        <el-form-item label="详细地址:" prop="address">
          <el-autocomplete
            v-model="form.address"
            style="width: 700px"
            popper-class="autoAddressClass"
            :fetch-suggestions="querySearchAsync"
            :trigger-on-focus="false"
            placeholder="详细地址"
            clearable
            @select="handleSelect"
          >
            <template slot-scope="{ item }">
              <i class="el-icon-search fl mgr10"/>
              <div style="overflow: hidden">
                <div class="title">{{ item.title }}</div>
                <span class="address ellipsis">{{ item.address }}</span>
              </div>
            </template>
          </el-autocomplete>
        </el-form-item>
        <!-- 地图的盒子-->
        <el-form-item label="地图定位:">
          <div id="map-container" style="width: 700px; height: 350px"/>
        </el-form-item>
        <!-- 按钮事件-->
        <el-form-item>
          <el-button type="primary" @click="onSubmit">确定</el-button>
          <el-button @click="handleClose">取消</el-button>
        </el-form-item>
      </el-form>
    </div>
  </el-dialog>
</template>

<script>
  /* 无须在引入,因为在父组件已经引入了 */
  //import loadBMap from "@/utils/loadBMap.js";

  export default {
    data() {
      return {
        dialogShow: false,//对话框状态
        dialogTitle: '地图定位',
        form: {
          address: "", // 详细地址
          addrPoint: {
            // 详细地址经纬度
            lng: 0,
            lat: 0,
          },
        },
        map: "", // 地图实例
        mk: "", // Marker实例
        locationPoint: null,
      };
    },

    methods: {
      //必须使用$nextTick不然第一次地图会初始化失败,第二次才看得地图
      // 必须使用$nextTick不然地图的创建坐标会比地图挂载还快。第一次会初始化失败
      myMehod() {
        //将对话框状态改为true,也就是打开对话框
        this.dialogShow = true
        this.$nextTick(() => {
          this.initMap()
        })
      },
      // 初始化地图
      initMap() {
        var that = this;
        // 1、挂载地图
        this.map = new BMap.Map("map-container", {enableMapClick: false});
        var point = new BMap.Point(119.30244559059787, 26.106339983665546);//默认点位
        this.map.centerAndZoom(point, 19);

        // 3、设置图像标注并绑定拖拽标注结束后事件
        this.mk = new BMap.Marker(point, {enableDragging: true});
        this.map.addOverlay(this.mk);
        this.mk.addEventListener("dragend", function (e) {
          that.getAddrByPoint(e.point);
        });

        // 4、添加(右上角)平移缩放控件
        this.map.addControl(
          new BMap.NavigationControl({
            anchor: BMAP_ANCHOR_TOP_RIGHT,
            type: BMAP_NAVIGATION_CONTROL_SMALL,
          })
        );

        // 5、添加(左下角)定位控件
        var geolocationControl = new BMap.GeolocationControl({
          anchor: BMAP_ANCHOR_BOTTOM_LEFT,
        });
        geolocationControl.addEventListener("locationSuccess", function (e) {
          that.getAddrByPoint(e.point);
        });
        geolocationControl.addEventListener("locationError", function (e) {
          //alert(e.message);
          console.log("locationError", e.message)
        });
        this.map.addControl(geolocationControl);

        // 6、浏览器定位
        this.geolocation();

        // 7、绑定点击地图任意点事件
        this.map.addEventListener("click", function (e) {
          that.getAddrByPoint(e.point);
        });
      },
      // 获取两点间的距离
      getDistancs(pointA, pointB) {
        return this.map.getDistance(pointA, pointB).toFixed(2);
      },
      // 浏览器定位函数
      geolocation() {
        var that = this;
        var geolocation = new BMap.Geolocation();
        geolocation.getCurrentPosition(
          function (res) {
            if (this.getStatus() == BMAP_STATUS_SUCCESS) {
              that.getAddrByPoint(res.point);
              that.locationPoint = res.point;
            } else {
              //alert("failed" + this.getStatus());
              console.log("failed", this.getStatus())
              that.locationPoint = new BMap.Point(119.30244559059787, 26.106339983665546);
            }
          },
          {enableHighAccuracy: true}
        );
      },
      // 2、逆地址解析函数
      getAddrByPoint(point) {
        var that = this;
        var geco = new BMap.Geocoder();
        geco.getLocation(point, function (res) {
          //console.log(res);
          that.mk.setPosition(point);
          that.map.panTo(point);
          that.form.address = res.address;
          that.form.addrPoint = point;
        });
      },
      // 8-1、地址搜索
      querySearchAsync(str, cb) {
        var options = {
          onSearchComplete: function (res) {
            var s = [];
            if (local.getStatus() == BMAP_STATUS_SUCCESS) {
              for (var i = 0; i < res.getCurrentNumPois(); i++) {
                s.push(res.getPoi(i));
              }
              cb(s);
            } else {
              cb(s);
            }
          },
        };
        var local = new BMap.LocalSearch(this.map, options);
        local.search(str);
      },
      // 8-2、选择地址
      handleSelect(item) {
        this.form.address = item.address + item.title;
        this.form.addrPoint = item.point;
        this.map.clearOverlays();
        this.mk = new BMap.Marker(item.point);
        this.map.addOverlay(this.mk);
        this.map.panTo(item.point);
      },
      //提交数据
      onSubmit() {
        // console.log('纬度:',this.form.addrPoint.lat);
        // console.log('经度:',this.form.addrPoint.lng);
        //传输数据
        this.$emit('afterSelectPosition', this.form)//子组件向父组件通信
        //提示框
        this.$confirm('地址确定好了吗, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          //将对话框状态改为false,也就是关闭对话框
          this.dialogShow = false
          //将文本域数据清空,不然第二次进来会有数据
          this.form.address = ''
        })
      },
      handleClose() {
        //将对话框状态改为false,也就是关闭对话框
        this.dialogShow = false
        //提示
        this.$message({
          type: 'success',
          message: "关闭地图"
        })
        //将文本域数据清空,不然第二次进来会有数据
        this.form.address = ''
      }
    },
  };
</script>

<style lang="scss" scoped>
  .autoAddressClass {
    li {
      i.el-icon-search {
        margin-top: 11px;
      }

      .mgr10 {
        margin-right: 10px;
      }

      .title {
        text-overflow: ellipsis;
        overflow: hidden;
      }

      .address {
        line-height: 1;
        font-size: 12px;
        color: #b4b4b4;
        margin-bottom: 5px;
      }
    }
  }
</style>

5.4 说明下组件通信

// 子组件
this.$emit('afterSelectPosition', this.form)


//父组件
<selectPosition ref="selectPositionWin" @afterSelectPosition="afterSelectPosition" />
重点在 @afterSelectPosition="afterSelectPosition"

//说明
afterSelectPosition这个必须一样,名字随便取,
@afterSelectPosition这个是父组件取值的方法

//父组件取值的方法
afterSelectPosition(data) {
   this.dataForm.mapLng = data.addrPoint.lng
   this.dataForm.mapLat = data.addrPoint.lat 
 }

六、其他用法说明

  1. 比如在一个范围内的打卡
  2. 硬件定位超出地图规定范围预警等一系列操作
  3. 获取多个经纬度的地点,在地图上使用标点显示
  4. 路线导航功能

还有不少用处,示例可以借鉴于百度地图api的示例demo ==> 入口


完结

  • 6
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
要实现百度地图关键字检索并自定义结果列表,可以按照以下步骤进行: 1. 引入百度地图 JavaScript API,并加载地图。 2. 在页面中添加一个输入框和一个按钮,用于输入关键字和触发检索。 3. 在按钮的点击事件中,调用百度地图关键字检索服务,传入关键字检索回调函数。 4. 在检索回调函数中,获取检索结果,并根据需要自定义结果列表。 下面是具体实现步骤: 1. 引入百度地图 JavaScript API,并加载地图。 ```html <!-- 加载百度地图 JavaScript API --> <script src="http://api.map.baidu.com/api?v=2.0&ak=您的密钥"></script> <!-- 创建一个地图容器 --> <div id="mapContainer"></div> <script> // 初始化地图 var map = new BMap.Map("mapContainer"); // 设置地图中心点和缩放级别 var point = new BMap.Point(116.404, 39.915); map.centerAndZoom(point, 15); </script> ``` 2. 添加输入框和按钮。 ```html <!-- 添加输入框和按钮 --> <input type="text" id="keywordInput"> <button onclick="search()">搜索</button> ``` 3. 调用百度地图关键字检索服务。 ```javascript function search() { // 获取输入框的值作为关键字 var keyword = document.getElementById("keywordInput").value; // 创建一个关键字检索服务实例 var local = new BMap.LocalSearch(map, { renderOptions: { map: map } }); // 搜索指定关键字 local.search(keyword, function(results) { // 获取检索结果 var pois = results ? results.getPoi(0) : null; // 根据需要自定义结果列表 if (pois) { var name = pois.title; var address = pois.address; var phone = pois.phone; // TODO: 在页面上显示自定义的结果列表 } }); } ``` 在检索回调函数中,我们首先获取检索结果,然后根据需要自定义结果列表。可以将检索结果中的名称、地址、电话等信息显示在页面上,也可以使用自己的样式和布局来展示检索结果。 这样,就可以实现百度地图关键字检索并自定义结果列表的功能了。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

suqinyi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值