微信小程序开发(四)公司营业网点列表
wxml 部分
本页面的功能是从云数据库中获取公司网点的名称、地址、经纬度信息、电话等,并将其展示到前端页面。wxml 部分没有太多复杂的场景,只是简单的样式堆砌,附代码:
<view class="container">
<view class='address-item' wx:for="{{newArray}}" wx:key="index">
<view class='address-text'>
<text class='address-text-title'>{{item.name}}<text class='address-text-distance'> -- 距离{{item.distance}}km</text></text>
<text class='address-text-subtitle'>{{item.address}}</text>
</view>
<view class='img-container' bindtap="onCallingTapped" data-id="{{item._id}}">
<image class='img' src='../../images/mypage_companies_phone.svg'></image>
</view>
<view class='img-container' bindtap="onLocatingTapped" data-id="{{item._id}}">
<image class='img' src='../../images/mypage_companies_location.svg'></image>
</view>
</view>
</view>
js 部分
第一步需要先从云数据库中取出所有数据并存入 data 字段的数组中。代码如下:
// 获取公司列表
getData: function() {
return new Promise((resolve, reject) => {
this.getListCount().then(res => {
let count = res
let list = []
for (let i = 0; i < count; i += 20) {
this.getListIndexSkip(i).then(res => {
list = list.concat(res)
if (list.length == count)
resolve(list)
})
}
})
})
},
// 获取公司列表长度
getListCount: function() {
return new Promise((resolve, reject) => {
db.collection('Mypage_Companies').count().then(res => {
resolve(res.total)
})
})
},
// 从第skip个位置开始获取20个列表记录
getListIndexSkip: function(skip) {
return new Promise((resolve, reject) => {
db.collection('Mypage_Companies').skip(skip).get().then(res => {
resolve(res.data)
})
})
},
需要注意的是,这里的 db.collection().get() 是异步调用的方法,所以如果希望获取到所有数据之后再执行计算或者排序,就得用 awake 关键字或者 Promise 风格来写代码。此处我采用的是 Promise 方法,因为小程序默认不支持 awake,除非开启增强编译。Promise 方法用 resolve 来返回需要返回的内容,会等到 resolve 中的变量已经生成完全后再返回到调用处,这样我们就通过循环获取到了数据库中的所有公司记录。
第二步是计算当前位置到每个网点的地理距离:
// 计算距离并根据距离排序
calculateDistanceAndSort: function(objectArray) {
var that = this;
wx.getLocation({
type: 'gcj02',
success: function(res) {
for (var i = 0; i < objectArray.length; i++) {
objectArray[i].distance = Number(that.distance(res.latitude, res.longitude, objectArray[i].location.latitude, objectArray[i].location.longitude))
}
that.setData({
objectArray: objectArray
})
that.newArray()
}
})
},
// 由经纬度计算两点之间的距离,la为纬度latitude缩写,lo为经度longitude的缩写
distance: function(la1, lo1, la2, lo2) {
var La1 = la1 * Math.PI / 180.0;
var La2 = la2 * Math.PI / 180.0;
var La3 = La1 - La2;
var Lb3 = lo1 * Math.PI / 180.0 - lo2 * Math.PI / 180.0;
var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(La3 / 2), 2) + Math.cos(La1) * Math.cos(La2) * Math.pow(Math.sin(Lb3 / 2), 2)));
s = s * 6378.137;
s = Math.round(s * 10000) / 10000;
s = s.toFixed(2);
return s;
},
这里借助了一个计算地球上两个经纬度之间距离的函数,从云数据库中取出来经纬度信息后拿进来算一算,再把算出来的结果赋给数组中对应公司的 distance 属性,然后调用 newArray() 方法根据距离远近进行排序,排序算法不再赘述。
最后一步是绑定电话和定位两个事件:
// 处理电话事件
onCallingTapped: function(e) {
let id = e.currentTarget.dataset.id
db.collection('Mypage_Companies').doc(id).get().then(res => {
let phone = res.data.phone
wx.showModal({
title: '提示',
content: '拨打电话:' + phone + '?',
success: function(res) {
if (res.confirm) {
wx.makePhoneCall({
phoneNumber: phone
})
}
}
})
})
},
// 处理定位事件
onLocatingTapped: function(e) {
let id = e.currentTarget.dataset.id
db.collection('Mypage_Companies').doc(id).get().then(res => {
let latitude = res.data.location.latitude
let longitude = res.data.location.longitude
let name = res.data.name
let address = res.data.address
wx.getLocation({
success: function(res) {
wx.openLocation({
latitude: latitude,
longitude: longitude,
scale: 26,
name: name,
address: address
})
}
})
})
}
wx.showModal() 方法可以弹出提示框让用户选择是否打电话,wx.makePhoneCall 方法可以直接跳转到拨号页。wx.getLocation() 获取当前用户的地理位置,然后调用 wx.openLocation(),其中的参数是当前用户选择的网点的经纬度和名称地址等信息。