一、引言
作者上一章讲了微信小程序的地图实现微信小程序(五)地图-CSDN博客,但是还有一个功能是和地图紧密结合的,那就是位置搜索定位,这里作者讲讲实现和原理,包括城市筛选。
二、定位搜索实现
1、位置搜索样式
这个其实就是样式啦,不是固定要和作者一样的
上面一个搜索框,下面展示搜索到的相关位置
<view class="top">
<view class="back iconfont icon-fanhui" bindtap="back1"></view>
<view class="search-box {{addListShow?'search-box1':''}}">
<view class="region" bindtap="chooseCity">{{currentRegion.district}}</view>
<view class="shu"></view>
<input class="input-box" bindinput="getsuggest" placeholder="请输入目标位置"></input>
</view>
</view>
<!--关键词输入提示列表渲染-->
<view class="add-list-box">
<scroll-view class="add-list" scroll-y>
<view class="add-item" wx:for="{{suggestion}}" wx:key="index">
<!--绑定回填事件-->
<view bindtap="backfill" id="{{index}}" data-name="{{item.title}}">
<!--根据需求渲染相应数据-->
<!--渲染地址title-->
<view class="title">{{item.title}}</view>
<!--渲染详细地址-->
<view class="add">{{item.addr}}</view>
</view>
</view>
</scroll-view>
2、拖动地图
随着地图拖拽,显示的附近位置也会改变
<cover-view class="top">
<cover-view class="back" bindtap="back1">
<cover-image src="/static/images/detail_back.png"></cover-image>
</cover-view>
<cover-view class="search-box">
<cover-view class="region" bindtap="chooseCity">{{currentRegion.district}}</cover-view>
<cover-view class="shu"></cover-view>
<cover-view class="placeholder" bindtap="showAddList">请输入地址</cover-view>
</cover-view>
</cover-view>
<cover-view class="map-prompt">您可拖动地图, 标记准确位置</cover-view>
<cover-image class="current-site-icon" src="/static/images/my_marker.png"></cover-image>
<cover-view class="reload" bindtap="reload">
<cover-view class="center1">
<cover-view class="center2"></cover-view>
</cover-view>
</cover-view>
3、附近位置样式
这里展示附近的位置,最终选定之后可以点击位置确认
<scroll-view class="near-list" scroll-y>
<!--绑定回填事件-->
<view class="near-item" wx:for="{{nearList}}" wx:key="index">
<view class="current-site iconfont icon-location" wx:if="{{index == selectedId }}"></view>
<!--根据需求渲染相应数据-->
<view bindtap="chooseCenter" id="{{index}}" data-name="{{item.title}}">
<!--渲染地址title-->
<view class="title {{ index == selectedId?'title1':'' }}">{{item.title}}</view>
<!--渲染详细地址-->
<view class="add {{ index == selectedId?'add1':'' }}">{{item.addr}}</view>
</view>
</view>
</scroll-view>
<view class="bottom-box">
<button bindtap="selectedOk">确认定位</button>
</view>
4、搜索附近位置
是根据选中的位置的经纬度进行搜索的,后端数据在腾讯地图
getsuggest: function (e) {
var _this = this;
var keyword = e.detail.value;
_this.setData({
addListShow: true
})
//调用关键词提示接口
qqmapsdk.getSuggestion({
//获取输入框值并设置keyword参数
keyword: keyword, //用户输入的关键词,可设置固定值,如keyword:'KFC'
location: _this.data.latitude + ',' + _this.data.longitude,
page_size: 20,
page_index: 1,
//region:'北京', //设置城市名,限制关键词所示的地域范围,非必填参数
success: function (res) {//搜索成功后的回调
//console.log(res);
var sug = [];
for (var i = 0; i < res.data.length; i++) {
sug.push({ // 获取返回结果,放到sug数组中
title: res.data[i].title,
id: res.data[i].id,
addr: res.data[i].address,
province: res.data[i].province,
city: res.data[i].city,
district: res.data[i].district,
latitude: res.data[i].location.lat,
longitude: res.data[i].location.lng
});
}
_this.setData({ //设置suggestion属性,将关键词搜索结果以列表形式展示
suggestion: sug,
nearList: sug,
keyword: keyword
});
},
fail: function (error) {
//console.error(error);
},
complete: function (res) {
//console.log(res);
}
});
},
nearby_search: function () {
var self = this;
wx.hideLoading();
wx.showLoading({
title: '加载中'
});
// 调用接口
qqmapsdk.search({
keyword: self.data.keyword,
location: self.data.latitude + ',' + self.data.longitude,
page_size: 20,
page_index: 1,
success: function (res) { //搜索成功后的回调
//console.log(res.data)
var sug = [];
for (var i = 0; i < res.data.length; i++) {
sug.push({ // 获取返回结果,放到sug数组中
title: res.data[i].title,
id: res.data[i].id,
addr: res.data[i].address,
province: res.data[i].ad_info.province,
city: res.data[i].ad_info.city,
district: res.data[i].ad_info.district,
latitude: res.data[i].location.lat,
longitude: res.data[i].location.lng
});
}
self.setData({
selectedId: 0,
centerData: sug[0],
nearList: sug,
suggestion: sug
})
self.addMarker(sug[0]);
},
fail: function (res) {
//console.log(res);
},
complete: function (res) {
//console.log(res);
}
});
},
5、地图拖动
根据拖动到的经纬度再次进行搜索
mapChange: function (e) {
let self = this;
if (e.type == 'end' && (e.causedBy == 'scale' || e.causedBy == 'drag')) {
self.mapCtx.getCenterLocation({
success: function (res) {
//console.log(res)
self.setData({
nearList: [],
latitude: res.latitude,
longitude: res.longitude,
})
self.nearby_search();
}
})
}
},
6、标记地图定位
addMarker: function (data) {
//console.log(data)
//console.log(data.title)
var mks = [];
mks.push({ // 获取返回结果,放到mks数组中
title: data.title,
id: data.id,
addr: data.addr,
province: data.province,
city: data.city,
district: data.district,
latitude: data.latitude,
longitude: data.longitude,
iconPath: "/images/my_marker.png", //图标路径
width: 25,
height: 25
})
this.setData({ //设置markers属性,将搜索结果显示在地图中
markers: mks,
currentRegion: {
province: data.province,
city: data.city,
district: data.district,
}
})
wx.hideLoading({});
},
7、效果
三、选择省市区实现
1、选择省市区样式
<view class="region-top">
<view class="region-back iconfont icon-fanhui" bindtap="back2"></view>
<view class="title">选择城市</view>
</view>
<view class="region-tabs">
<text class="tab" bindtap="showProvince">{{currentProvince}}</text>
<text class="tab" bindtap="showCity" >{{currentCity}}</text>
<text class="tab" bindtap="showDistrict" >{{currentDistrict}}</text>
</view>
<scroll-view scroll-y style="height:1050rpx;">
<view class="region-list" wx:if="{{regionShow.province}}">
<view class="region-item" wx:for="{{regionData.province}}" wx:key="index">
<view data-id="{{item.id}}" data-name="{{item.fullname}}" bindtap="selectProvince">
<text>{{item.fullname}}</text>
</view>
</view>
</view>
<view class="region-list" wx:if="{{regionShow.city}}">
<view class="region-item" wx:for="{{regionData.city}}" wx:key="index">
<view data-id="{{item.id}}" data-name="{{item.fullname}}" bindtap="selectCity">
<text>{{item.fullname}}</text>
</view>
</view>
</view>
<view class="region-list" wx:if="{{regionShow.district}}">
<view class="region-item" wx:for="{{regionData.district}}" wx:key="index">
<view data-id="{{item.id}}" data-name="{{item.fullname}}"
data-latitude="{{item.location.lat}}" data-longitude="{{item.location.lng}}"
bindtap="selectDistrict">
<text>{{item.fullname}}</text>
</view>
</view>
</view>
2、省市区缓存
省市区相当于先是几个层级的筛选,所以得先从地图查一下进行级联缓存,不然每次调用地图卡死了,用户体验会很差
getRegionData: function () {
let self = this;
console.log('调用获取城市列表接口')
//调用获取城市列表接口
qqmapsdk.getCityList({
success: function (res) {//成功后的回调
console.log(res)
let provinceArr = res.result[0];
let cityArr = [];
let districtArr = [];
for (var i = 0; i < provinceArr.length; i++) {
var name = provinceArr[i].fullname;
if (self.data.currentRegion.province == name) {
// if (name == '北京市' || name == '天津市' || name == '上海市' || name == '重庆市') {
// cityArr.push(provinceArr[i])
// } else {
qqmapsdk.getDistrictByCityId({
// 传入对应省份ID获得城市数据,传入城市ID获得区县数据,依次类推
id: provinceArr[i].id,
success: function (res) {//成功后的回调
//console.log(res);
cityArr = res.result[0];
console.log('setData');
self.setData({
regionData: {
province: provinceArr,
city: cityArr,
district: districtArr
}
})
},
fail: function (error) {
console.error(error);
},
complete: function (res) {
console.log(res);
}
});
}
// }
}
console.log('now res:{}', res);
console.log('self.data.currentRegion:{}', JSON.stringify(self.data.currentRegion));
},
fail: function (error) {
console.error(error);
},
complete: function (res) {
console.log(res);
}
});
},
3、打开省市区页面
chooseCity: function () {
let self = this;
self.getRegionData();
self.setData({
chooseCity: true,
regionShow: {
province: true,
city: false,
district: false
},
currentProvince: self.data.currentRegion.province,
currentCity: self.data.currentRegion.city,
currentDistrict: self.data.currentRegion.district,
})
},
4、选择省市区
showProvince: function () {
console.log('showProvince')
console.log(this.data.regionData.province)
this.setData({
regionShow: {
province: true,
city: false,
district: false
}
})
},
//选择城市
showCity: function () {
this.setData({
regionShow: {
province: false,
city: true,
district: false
}
})
},
//选择地区
showDistrict: function () {
this.setData({
regionShow: {
province: false,
city: false,
district: true
}
})
},
selectProvince: function (e) {
//console.log(e)
let self = this;
let id = e.currentTarget.dataset.id;
let name = e.currentTarget.dataset.name;
self.setData({
currentProvince: name,
currentCity: '请选择城市',
})
if (name == '北京市' || name == '天津市' || name == '上海市' || name == '重庆市') {
var provinceArr = self.data.regionData.province;
var cityArr = [];
for (var i = 0; i < provinceArr.length; i++) {
if (provinceArr[i].fullname == name) {
cityArr.push(provinceArr[i])
self.setData({
regionData: {
province: self.data.regionData.province,
city: cityArr,
district: self.data.regionData.district
}
})
self.showCity();
return;
}
}
} else {
let bj = self.data.regionShow;
self.getById(id, name, bj)
}
},
//选择城市之后操作
selectCity: function (e) {
let self = this;
let id = e.currentTarget.dataset.id;
let name = e.currentTarget.dataset.name;
self.setData({
currentCity: name,
currentDistrict: '请选择城市',
})
let bj = self.data.regionShow;
self.getById(id, name, bj)
},
//选择区县之后操作
selectDistrict: function (e) {
let self = this;
let id = e.currentTarget.dataset.id;
let name = e.currentTarget.dataset.name;
let latitude = e.currentTarget.dataset.latitude;
let longitude = e.currentTarget.dataset.longitude;
self.setData({
currentDistrict: name,
latitude: latitude,
longitude: longitude,
currentRegion: {
province: self.data.currentProvince,
city: self.data.currentCity,
district: name
},
chooseCity: false,
keyword: self.data.defaultKeyword
})
self.nearby_search();
},
//根据选择省市加载市区列表
getById: function (id, name, bj) {
let self = this;
qqmapsdk.getDistrictByCityId({
// 传入对应省份ID获得城市数据,传入城市ID获得区县数据,依次类推
id: id, //对应接口getCityList返回数据的Id,如:北京是'110000'
success: function (res) {//成功后的回调
//console.log(res);
if (bj.province) {
self.setData({
regionData: {
province: self.data.regionData.province,
city: res.result[0],
district: self.data.regionData.district
}
})
self.showCity();
} else if (bj.city) {
self.setData({
regionData: {
province: self.data.regionData.province,
city: self.data.regionData.city,
district: res.result[0]
}
})
self.showDistrict();
} else {
self.setData({
chooseCity: false,
})
}
},
fail: function (error) {
//console.error(error);
},
complete: function (res) {
//console.log(res);
}
});
},
4、确认定位
这个要看啦,作者是在同一个页面,只是把地图当成一个弹窗,所以只要关闭弹窗就行,变量设置到这个页面了
如果地图是另外一个页面,还要跳转的时候把数据带过去
5、效果
四、总结
定位的搜索和省市区筛选基本就这样了,后端是依赖腾讯地图的,作者在之前的文章也写了怎么引用腾讯地图,有疑问的小伙伴欢迎评论区私聊。