1.背景:
在微信小程序中,地图上展示一个坐标点周边的医院学校等周边设施,通过地图上气泡的方式。点击气泡展示不同的气泡状态,点击导航跳转到对应气泡点所在的坐标位置。
2.实现思路:
2.1布局:
地图全屏展示,地图上的位置tablist展示在地图底部,跳转导航按钮位于地图右上角。因为map属于原生标签,而且层级比较高,所以tablist和按钮都需要通过cover-view和cover-image来提高层级。官网传送门
2.2map部分:
需要在地图上做标记,通过marks进行标记点(cover即将废弃,点击跳转官网);
地图上气泡点的点击事件是通过给map添加bindcallouttap来实现的,点击去官网查看;
获取当前点击的气泡是通过 bindcallouttap的 “点击标记点对应的气泡时触发e.detail = {markerId}
”,官网中也有说明;
map跳转导航,通过wx.openLocation的api来实现的,点击去官网;
2.3 腾讯地图SDK:
需要通过坐标点来获取周边的位置,肯定需要用到第三方的SDK来查找,点击官网传送门,比较简单明了,大概看一下就会用了:
几点说明:
① 需要申请密匙;
② 加入合法域名;
③ 下载 qqmap-wx-jssdk.min.js 包并且引入;
④ 这个地方主要使用 qqmapsdk.search 查找方法(传入关键词,写入一个需要几条(不写默认10条),传入经纬度(用逗号拼接),然后对获取的数据进行处理为自己所需要的格式);
⑤ 当然了,对于接口所返回的distance如果感觉不准确的话可以使用距离计算的方法 qqmapsdk.calculateDistance,传入起始点的坐标位置,传入终点位置(终点可以是一个点页可以是多个点,通过坐标的方式可以计算的,具体使用可以参考官网,写的也比较详细);
3.代码实现:
3.1wxml
3.2 css
/*弹性布局*/
.flex {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
display: box;
flex-wrap:wrap;
}
.noWarp{
flex-wrap:nowrap;
}
/*元素居中*/
.alignC{
align-items: center;
-webkit-box-align: center;
-webkit-align-items: center;
-moz-align-items: center;
-ms-align-items: center;
-o-align-items: center;
}
/*水平排列*/
.flexH{
-webkit-box-orient: horizontal;
-webkit-flex-direction: row;
-moz-flex-direction: row;
-ms-flex-direction: row;
-o-flex-direction: row;
flex-direction: row;
}
/*垂直排列*/
.flexV {
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
-moz-flex-direction: column;
-ms-flex-direction: column;
-o-flex-direction: column;
flex-direction: column;
}
/*两端对齐*/
.flexSa {
-webkit-box-pack: justify;
justify-content: space-around;
-webkit-justify-content: space-around;
-moz-justify-content: space-around;
-ms-justify-content: space-around;
-o-justify-content: space-around;
}
/*居中对齐*/
.flexC {
-webkit-box-pack: center;
justify-content: center;
-webkit-justify-content: center;
-moz-justify-content: center;
-ms-justify-content: center;
-o-justify-content: center;
}
.flexSb {
justify-content: space-between;
-webkit-justify-content: space-between;
-moz-justify-content: space-between;
-ms-justify-content: space-between;
-o-justify-content: space-between;
}
.flexS {
-webkit-box-pack: start;
justify-content: flex-start;
-webkit-justify-content: flex-start;
-moz-justify-content: flex-start;
-ms-justify-content: flex-start;
-o-justify-content: flex-start;
}
.flexE {
-webkit-box-pack: end;
justify-content: flex-end;
-webkit-justify-content: flex-end;
-moz-justify-content: flex-end;
-ms-justify-content: flex-end;
-o-justify-content: flex-end;
}
.tfLine1 {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
/* 页面内容 */
.xmwzB{
position: absolute;
left: 0;
bottom: 0;
width: 100%;
background-color: rgba(255, 255, 255, 0.6);
box-sizing: border-box;
padding: 20rpx 25rpx;
}
.xmwzBLi{
background-size:48rpx 48rpx;
background-repeat: no-repeat;
background-position:top center;
padding-top: 72rpx;
text-align: center;
font-size: 30rpx;
color: #333333;
padding-bottom: 30rpx;
position: relative;
}
.xmwzBLi:before{
position: absolute;
width: 100%;
height: 10rpx;
background-color: transparent;
left: 0;
bottom: 0;
display: block;
content:'';
}
.xmwzBLi.on::before{
background-color: #3072f6;
}
.xmwzBLi .img{
position: absolute;
left: 50%;
top: 5rpx;
margin-left: -24rpx;
width: 48rpx;
height: 48rpx;
}
.xmwzUl{
padding: 15rpx 0 50rpx;
}
.xmwzUl-li{
height: 60rpx;
line-height: 60rpx;
}
.xmwzUl-li-name{
font-size: 30rpx;
color: #666666;
}
.xmwzUl-li-add{
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAeCAMAAAAB8C7XAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkY5QTYwM0Y5NzhBNDExRUE4RUQ0Q0YzMkJFMDVDRjRGIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkY5QTYwM0ZBNzhBNDExRUE4RUQ0Q0YzMkJFMDVDRjRGIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6RjlBNjAzRjc3OEE0MTFFQThFRDRDRjMyQkUwNUNGNEYiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6RjlBNjAzRjg3OEE0MTFFQThFRDRDRjMyQkUwNUNGNEYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7eVhRAAAAAGFBMVEX19fX9/f3k5OTt7e3l5eX////Z2dkAAADwxi4GAAAACHRSTlP/////////AN6DvVkAAAB3SURBVHjajNJREoAgCATQJTPuf+PKRFHYmfhrX6UoUKur1XiET70h5F0Q80+Q5E2Q5a8gzR+ZcEAER4RSW5UB9n7tZd8YwAAbiIH8BfqruDjd7mjw3BukZ8WBHju/KA70zvmUeFnnaoruQCbRRDNQny+gHm4BBgBoDxEM+vumxAAAAABJRU5ErkJggg==);
background-size:24rpx 30rpx;
background-repeat: no-repeat;
background-position: left center;
padding-left:36rpx;
font-size: 30rpx;
color: #aaaaaa;
}
.navigation_btn{
width:76rpx;
height:76rpx;
position: absolute;
right:30rpx;
top:50rpx;
}
3.3js
var QQMapWX = require('../../lib/qqmap-wx-jssdk.min.js');
var qqmapsdk;
qqmapsdk = new QQMapWX({
key: 'RAMBZ-UKXW6-FZOSO-M6ENO-RCTTE-THFBQ'
});
Page({
/**
* 页面的初始数据
*/
data: {
// 获取的经纬度
t_lat: '32.00335',
t_lng: '118.73145',
// 地图的markers
markers: [],
// 当前选中第几个
xmwzB_index: 0,
// tab列表
tabs: [{
ico: '../../images/around/icon1.png',
ico_active: '../../images/around/icon1_1.png',
name: '交通'
},
{
ico: '../../images/around/icon2.png',
ico_active: '../../images/around/icon2_1.png',
name: '学校'
},
{
ico: '../../images/around/icon3.png',
ico_active: '../../images/around/icon3_1.png',
name: '医疗'
},
{
ico: '../../images/around/icon4.png',
ico_active: '../../images/around/icon4_1.png',
name: '购物'
},
{
ico: '../../images/around/icon5.png',
ico_active: '../../images/around/icon5_1.png',
name: '餐饮'
},
],
// 把从腾讯地图SDK获取的位置存起来,以后每次点击就不用请求了。
arrlist: [
[],
[],
[],
[],
[]
],
// 记录当前地图选中的icon点
location: ['', '', '', '', ''],
// 是否展示地图跳转导航按钮
navigation: false,
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
var that = this;
var marks = [];
// 地图上的icon图标
marks.push({ // 获取返回结果,放到mks数组中
latitude: that.data.t_lat,
longitude: that.data.t_lng,
iconPath: '../../images/around/address.png', //图标路径
width: 20,
height: 20,
});
// 地图上的气泡点
that.setData({
markers: marks
});
// 进页面先请求一波(第一个tab下对应的列表内容)
that.nearby_search(that.data.tabs[0].name);
},
// 点击tab切换
xmwzB_click(e) {
var that = this;
var index = e.currentTarget.dataset.index;
that.setData({
xmwzB_index: index
}, () => {
var name = that.data.tabs[index].name;
that.nearby_search(name);
});
},
// 通过关键字调用地图SDK,搜索获取结果列表
nearby_search(key) {
var that = this;
var xmwzB_index = that.data.xmwzB_index;
var list_c = that.data.arrlist[xmwzB_index];
// 判断是否请求过了,如果没请求过则请求;请求过了就直接赋值
if (list_c && list_c.length) {
that.setData({
markers: list_c
});
} else {
wx.showToast({
title: '请稍后',
icon: 'loading',
duration: 2000
})
qqmapsdk.search({
keyword: key, // 搜索关键词
page_size: 5, // 一页展示几个
location: that.data.t_lat + ',' + that.data.t_lng, //设置周边搜索中心点
success: function (res) { //搜索成功后的回调
wx.hideToast({});
var marks = [];
marks.push({ // 获取返回结果,放到mks数组中
latitude: that.data.latitude,
longitude: that.data.longitude,
iconPath: '../../images/around/address.png', //图标路径
width: 20,
height: 20,
});
for (var i = 0; i < res.data.length; i++) {
marks.push({ // 获取返回结果,放到mks数组中
title: res.data[i].title,
id: res.data[i].id,
latitude: res.data[i].location.lat,
longitude: res.data[i].location.lng,
iconPath: '../../images/around/cover_1.png', //图标路径
width: 20,
height: 20,
address: res.data[i].address,
callout: {
content: res.data[i].title,
color: '#404040',
bgColor: '#ffffff',
borderWidth: 1,
borderColor: '#8a8a8a',
fontSize: 14,
padding: 10,
borderRadius: 10,
display: 'ALWAYS'
}
});
}
// 只赋值当前tab下的内容,其他tab下的不用管
var arrlist_key = 'arrlist[' + xmwzB_index + ']';
that.setData({ //设置markers属性,将搜索结果显示在地图中
[arrlist_key]: marks,
markers: marks
});
},
fail: function (res) {
console.log(res);
},
complete: function (res) {
//console.log(res.data);
}
});
}
},
// 地图上的气泡点击事件绑定,具体详情可参考微信小程序地图api
callouttap(e) {
var that = this;
var marks = that.data.markers;
// 点击某个tab下的某个气泡,其他气泡恢复为初始状态,点击的气泡变为选中状态
// 同时把选中的状态的气泡信息存入到location对应位置(给点击跳转导航做准备)
for (var i = 0; i < marks.length; i++) {
if (marks[i].callout == undefined) {
continue
}
marks[i].callout.bgColor = '#ffffff';
marks[i].callout.color = '#404040'
marks[i].callout.borderColor = '#8a8a8a'
}
that.setData({
markers: marks,
navigation: true,
['markers[' + that.data.markers.findIndex((n) => n.id == e.markerId) + '].callout.bgColor']: '#558ef9',
['markers[' + that.data.markers.findIndex((n) => n.id == e.markerId) + '].callout.color']: '#ffffff',
['markers[' + that.data.markers.findIndex((n) => n.id == e.markerId) + '].callout.borderColor']: '#558ef9',
['location[' + that.data.xmwzB_index + ']']: that.data.markers[that.data.markers.findIndex((n) => n.id == e.markerId)]
});
},
// 小程序地图api,跳转大地图
show_big_map: function () {
var that = this;
var location_c = that.data.location[that.data.xmwzB_index];
var lat_c = location_c.latitude ? location_c.latitude : '';
var lng_c = location_c.longitude ? location_c.longitude : '';
var name_c = location_c.title ? location_c.title : '';
var address_c = location_c.address ? location_c.address : '';
if (location_c && lat_c && lng_c && name_c && address_c) {
wx.getLocation({ //获取当前经纬度
type: 'wgs84', //返回可以用于wx.openLocation的经纬度,官方提示bug: iOS 6.3.30 type 参数不生效,只会返回 wgs84 类型的坐标信息
success: function (res) {
wx.openLocation({ //使用微信内置地图查看位置。
latitude: lat_c, //要去的纬度-地址
longitude: lng_c, //要去的经度-地址
name: name_c,
address: address_c
});
}
})
}
}
})
3.4效果
4.说明
4.1 之前也写过一个比较简单的,只是展示列表的,如果需要也可以去瞅瞅,点击传送门;
4.2 也可以去百度云盘下载完整代码:
链接:https://pan.baidu.com/s/19Lx3PDsysSbYvYOUJmyLaA
提取码:blmx
4.3 也可去Git下载实例:https://github.com/hangGe110305/Wechat-applet-search-around-of-the-map