今天介绍百度地图搜索的第二种用法,之前记录过一种方法(详细可看百度地图的使用(一))。第一种方法是通过BMap.LocalSearch来自定义搜索,拿返回Yr参数去渲染页面。最近使用百度搜索发现不同的电脑返回的参数不一样,导致有的电脑搜索是null。若想继续使用这个方法,可以做以下改进。
const local = new this.BMap.LocalSearch(this.map, {
renderOptions: {
map: this.map,
selectFirstResult: false
},
onSearchComplete: function(res) {
console.log('results', res)
if (res && (res.Yr || res.as)) { // 若res.Yr不存在则取res.as,在网上没找到为什么会返回不一样的参数,但目前只发现这两种。
this.searchResult = [...(res.Yr || res.as)]
}
}
})
local.search(this.keyword)
尽管做了上面的改进,还是觉得不太保险。若有第三种返回参数,还需要再加,这种情况还不可控。于是换了一种方法,通过请求百度地图提供的api来搜索。具体代码如下:
<template>
<div>
<div class="search-wrap">
<div class="search">
<input v-model="keyword" class="search-input" type="text" @input="search">
<el-button type="primary" size="small" @click="handleSubmit">确认</el-button>
</div>
<!-- 检索结果 -->
<div v-show="showResultFlag" class="search-result">
<div v-for="(item, index) in results" :key="index" class="item" @click="handleSelect(item)">
<p class="title">{{ item.name }}</p>
<p class="address">{{ item.address }}</p>
</div>
</div>
</div>
</div>
<baidu-map
class="bm-view"
ak="XXX"
:center="mapCenter"
:zoom="mapZoom"
:scroll-wheel-zoom="true"
@ready="onReady"
@click="getClickInfo"
/>
</div>
</template>
<script>
import BaiduMap from 'vue-baidu-map/components/map/Map.vue'
const defaultInfo = {
lng: 0,
lat: 0,
addressStr: '',
title: '',
province: '', // 省
city: '', // 市
district: '' // 区
}
export default {
name: 'MapMaker',
components: {
BaiduMap
},
data() {
return {
ssq: {
provinceName: '',
cityName: '',
districtName: ''
},
BMap: null,
map: null,
mapZoom: 15,
mapCenter: { lng: 121.329402, lat: 31.228667 },
keyword: '',
searchResult: [], // 检索结果列表
showResultFlag: true, // 控制是否展示搜索的结果
selectInfo: Object.assign({}, defaultInfo)
}
},
methods: {
search() {
const city = this.city || '北京市' // 最好有一个默认的城市,否则可能会有返回的数据为空的情况
if (!this.keyword) {
this.showResultFlag = false
} else {
this.showResultFlag = true
}
// 这里使用百度提供的api来搜索,搜索的关键词最好加一个encodeURIComponent方法(如下),不然在ie浏览器会变成乱码,报错。如果项目对ie浏览器不是硬性要求的话,可以不加。
if (this.keyword && this.keyword.length > 0) {
$.ajax({
url: `https://api.map.baidu.com/place/v2/suggestion?query=${encodeURIComponent(this.keyword)}®ion=${encodeURIComponent(city)
}&city_limit=false&output=json&ak=xxxxxx`,
type: 'GET',
contentType: 'application/json;charset=utf-8',
dataType: 'jsonp', // 这里要用jsonp的方式不然会报错
success: (data) => {
this.results = data.result
}
})
}
},
// 地图初始化回调
onReady({ BMap, map }) {
this.BMap = BMap
this.map = map
},
handleSelect(item) {
const self = this
console.log('item', item)
this.city = item.city
const { lng, lat } = item.location
const point = new this.BMap.Point(lng, lat)
const geoc = new this.BMap.Geocoder()
geoc.getLocation(point, function(res) {
console.log('res------------', res)
const addString =
res.addressComponents.province + res.addressComponents.city + res.addressComponents.district + title
self.showResultFlag = false
self.keyword = addString
self.map.clearOverlays() // 清除地图上所有覆盖物
self.map.addOverlay(new self.BMap.Marker({ lng, lat }))
self.mapCenter.lng = lng
self.mapCenter.lat = lat
self.mapZoom = 18
self.selectInfo = {
lng,
lat,
addressStr: addString,
title: title,
province: res.addressComponents.province,
city: res.addressComponents.city,
district: res.addressComponents.district
}
})
},
handleSubmit() {
// 我的百度地图是组件,在这一步触发父组件的方法提交数据
this.$emit('submitAddressFun', this.selectInfo)
},
// 在地图上选取
getClickInfo(e) {
console.log(e)
this.mapCenter.lng = e.point.lng
this.mapCenter.lat = e.point.lat
const BMapGL = this.BMap
const map = this.map
map.clearOverlays()
const marker = new BMapGL.Marker(
new BMapGL.Point(e.point.lng, e.point.lat)
)
map.addOverlay(marker)
// 创建地理编码实例
// eslint-disable-next-line no-undef
const myGeo = new BMap.Geocoder()
// 根据坐标逆解析地址
// eslint-disable-next-line no-undef
myGeo.getLocation(new BMap.Point(e.point.lng, e.point.lat), (result) => {
console.log('打印result------', result)
if (result) {
// 我的代码其实是用的result.surroundingPois[0]的address,手动点击地图获取地址,总是没有输入的准确,导致手动获取的地址总是不完整,所以我就没用result.address,这里就仁者见仁,智者见智。
// const surroundAdd = result.surroundingPois[0] // 这个是选取周围建筑地第一个
// this.keyword = surroundAdd.address
if (result.address) { // 会出现一种情况,就是返回的address是空的,这个时候就要自己拼接一下
this.keyword = result.address
} else {
const ad = result.addressComponents
this.keyword = ad.province + ad.city + ad.district + ad.street + ad.streetNumber
}
}
})
}
}
}
</script>
<style lang="scss" scoped>
.map-maker-wrapper {
position: relative;
}
.btn-confrim {
width: 120px;
height: 56px;
line-height: 56px;
background-color: #5ac9d4;
border-radius: 8px;
color: #ffffff;
text-align: center;
}
.bm-view {
// margin-top: 30px;
width: 100%;
height: calc(100vh - 88px);
}
.search-wrap {
position: relative;
width: 350px;
box-sizing: border-box;
padding: 0 32px;
.search {
z-index: 5;
width: 450px;
height: 30px;
position: absolute;
top: -66px;
left: 30%;
}
.search input {
float: left;
width: 350px;
height: 100%;
border: 1px solid #30ccc1;
padding: 0 8px;
outline: none;
}
.search button {
float: left;
/*width: 20%;*/
height: 100%;
background: #30ccc1;
border: 1px solid #30ccc1;
color: #fff;
outline: none;
}
.search-result {
position: absolute;
top: -34px;
left: 30%;
width: 406px;
z-index: 5;
background-color: #fff;
padding: 0 32px;
border-radius: 10px;
max-height: 420px;
overflow-y: scroll;
.item {
border-bottom: 1px solid #ebeef2;
// padding: 32px 0;
&:last-child {
border-bottom: none;
}
.title {
font-size: 14px;
font-weight: 600;
color: #313233;
margin: 10px 0 5px;
}
.address {
font-size: 12px;
font-weight: 400;
color: #9ca5b3;
margin: 5px 0 10px;
// margin-top: 8px;
}
}
}
}
</style>
安装引入百度地图可以看vue之百度地图的使用(一),这里记录的两种方法最大的区别就是搜索地址的方式不一样。尽管都能实现功能,但个人建议通过百度地图api去搜索更好。