前言
因业务需求微信小程序使用wx.getLocation和腾讯地图联合实现打卡功能,并且记录一下
需要满足以下条件
- 一个已开通
wx.getLocation
接口权限的微信小程序 - 注册一个腾讯地图开放平台,并创建一个key 申请key
申请 wxgetLocation 接口权限时,可事先将前端页面静态页面实现截图上传辅助审核更容易通过
一、下载并引用sdk包
可以点击前面的 申请key 链接进入页面下载相应的包,并在页面中引入
/* 根据自己实际业务,随意放置位置*/
var QQMapWX = require("../../utils/qqmap-wx-jssdk/qqmap-wx-jssdk")
var qqmapwx;
Page({
data:{
targetLocation:[0,0]
},
onLoad(){
qqmapwx = new QQMapWX({
key: "申请的key"
})
qqmapwx.geocoder({
address: "北京天安门",
success: function (res) {
_this.setData({
targetLocation: res.result.location
})
}
})
}
})
wxml代码
<view>
<map style="width:100%;height:500rpx;margin-top:20rpx;"
name="dk"
longitude="{{targetLocation.lng}}"
latitude="{{targetLocation.lat}}"
>
</map>
</view>
二、标记打卡点
前面通过 qqmapwx.geocoder({address:'北京天安门'})
获取到了北京天安门的坐标,我们就以天安门的坐标为打卡点
定义一个创建地图标记的方法
/*------------------------util.js---------------------------------*/
function randId(len = 32) {
let date = (new Date()).valueOf()
console.log(date)
let txt = '1234567890qwertyuioplkjhgfdsazxcvbnm'
let pwd = ''
for (let index = 0; index < len; index++) {
pwd += txt.charAt(Math.floor(Math.random() * txt.length))
}
return pwd
}
/*---------------------------------------------------------*/
const {
randId
} = require("../../utils/util")
var QQMapWX = require("../../utils/qqmap-wx-jssdk/qqmap-wx-jssdk")
var qqmapwx;
let marker = [] // 在Page()前面定义一个变量用了存储标记点,在后面还要在存一个用户当前所在位置的点
Page({
data: {
targetLocation: [0, 0]
},
onLoad() {
qqmapwx = new QQMapWX({
key: "申请的key"
})
qqmapwx.geocoder({
address: "北京天安门",
success: function (res) {
_this.setData({
targetLocation: res.result.location
})
_this.addMark(res.result.location.lng, res.result.location.lat, "北京天安门")
}
})
},
addMark(lng, lat, name) {
marker.push({
id: randId(), //标记点 id
width: 50,
height: 50,
longitude: lng,
latitude: lat,
label: {
content: name,
color: '#f00',
textAlign: "center",
fontSize: 12
},
callout: {
content: '气泡',
color: "#f00",
fontSize: 30
},
})
this.setData({
markers: marker
})
}
})
wxml代码
<view>
<map style="width:100%;height:500rpx;margin-top:20rpx;"
name="dk"
longitude="{{targetLocation.lng}}"
latitude="{{targetLocation.lat}}"
markers="{{markers}}"
>
</map>
</view>
3、获取用户当前位置
获取用户当前位置信息使用wx.getLocation()
注意:wx.getLocation 并不能直接使用,需要申请权限,并且在app.json里面配置
{
"pages":[
"pages/index/index"
],
"requiredPrivateInfos": [
"getLocation"
],
"permission": {
"scope.userLocation": {
"desc": "获取位置信息弹框询问信息"
}
},
}
wx.getLocation 获取用户当前位置
微信开发工具的定位是采用的 IP定位,存在误差并且只支持 gcj02
data:{
targetLocation:[0,0]
userInfo:{
location:[0,0],
}
},
getUserLocation() {
const _this = this
wx.getLocation({
type: 'gcj02', // 腾讯地图的坐标系采用的gcj02
success: function (res) {
console.log(res)
_this.setData({
["userInfo.location"]: [res.latitude, res.longitude]
})
}
})
},
使用 qqmapwx.reverseGeocoder
将获取到的坐标转换为中文地址信息 ,并在地图上标记
getUserLocation() {
const _this = this
wx.getLocation({
type: 'gcj02', // 腾讯地图的坐标系采用的gcj02
success: function (res) {
console.log(res)
_this.setData({
["userInfo.location"]: [res.latitude, res.longitude]
})
_this.addMark(res.longitude, res.latitude, "我") // 标记
qqmapwx.reverseGeocoder({
location: {
latitude: res.latitude,
longitude: res.longitude
},
success(resp) {
_this.setData({
["userInfo.address"]: resp.result.address,
})
}
})
}
})
},
wxml代码
<view> 纬度:{{userInfo.location[0]}} ,经度:{{userInfo.location[1]}}</view>
<view style="height: 60rpx;line-height:60rpx;"> 当前位置:{{userInfo.address}}</view>
三、计算两点之间的距离
function rad(d) {
return d * Math.PI / 180.0
}
// 计算两个坐标点的直线距离
function distanceOf(p1, p2) {
let radLng1 = rad(p1.x)
let radLng2 = rad(p2.x)
let mdifference =radLng1 - radLng2
let difference = rad(p1.y) - rad(p2.y)
let distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(difference / 2), 2) +
Math.cos(radLng1) * Math.cos(radLng2) * Math.pow(Math.sin(mdifference / 2), 2)));
// 弧长等于弧度乘地球半径(单位为米)
distance = distance * 6378.137;
// 精确距离的数值
distance = Math.abs(Math.round(distance * 10000) / 10);
return distance
}
在业务js文件中引入
const {
distanceOf,
randId
} = require("../../utils/util")
/*---------------------------------------------------------*/
// distanceOf 方法调用位置根据业务需求,我这边就放在获取到用户位置后
getUserLocation() {
const _this = this
wx.getLocation({
type: 'gcj02', // 腾讯地图的坐标系采用的gcj02
success: function (res) {
console.log(res)
_this.setData({
["userInfo.location"]: [res.latitude, res.longitude]
})
_this.addMark(res.longitude, res.latitude, "我")
const dis = distanceOf({
"x": _this.data.targetLocation.lng,
"y": _this.data.targetLocation.lat
}, {
"x": res.longitude,
"y": res.latitude
})
qqmapwx.reverseGeocoder({
location: {
latitude: res.latitude,
longitude: res.longitude
},
success(resp) {
_this.setData({
["userInfo.address"]: resp.result.address,
["userInfo.dis"]: dis
})
}
})
}
})
},
wxml
<view>
</button>
<view> 纬度:{{userInfo.location[0]}} ,经度:{{userInfo.location[1]}}</view>
<view style="height: 60rpx;line-height:60rpx;"> 当前位置:{{userInfo.address}}</view>
<view>距离打卡点还有:{{userInfo.dis}}米</view>
</view>
<map style="width:100%;height:500rpx;margin-top:20rpx;" name="dk" longitude="{{targetLocation.lng}}" latitude="{{targetLocation.lat}}" markers="{{markers}}">
</map>
微信开发工具
小程序
四、页面优化
页面简单的调整
wxml
<view class="content1">
<view class="boxm">
<view class="box" style="border-right-color: {{userInfo.jl< 100 ?'#0f0':'#f60' }};">
</view>
<view class="boxtext">
<view> 距离:{{userInfo.dis}}米</view>
</view>
</view>
<view class="dk-text">
<button bindtap="bindClock" class='dk-btn'>{{userInfo.jl <100?'正常打卡':'外勤打卡'}} </button>
<view style="height: 60rpx;line-height:60rpx;"> 当前位置:{{userInfo.address}}</view>
</view>
<map class="map" name="dk" longitude="{{targetLocation.lng}}" latitude="{{targetLocation.lat}}" markers="{{markers}}">
</map>
</view>
全部wxss
.content1 {
height: auto;
background: white;
margin-top: 24rpx;
width: 702rpx;
margin-left: 24rpx;
border-radius: 25rpx;
padding: 20rpx 0;
}
.contentBox1 {
width: 702rpx;
border: 1rpx solid white;
display: flex;
}
.time {
background: #F4F5F7;
width: 315rpx;
height: 120rpx;
margin-top: 24rpx;
margin-left: 24rpx;
border-radius: 20rpx;
}
.boxm {
width: 260rpx;
height: 260rpx;
position: relative;
transform-origin: 50% 50%;
margin: auto;
text-align: center;
}
.box {
width: 260rpx;
height: 260rpx;
border: 4px solid rgb(196, 192, 192);
border-right: 4px solid #f60;
border-radius: 50%;
animation: turn 1s linear infinite;
}
.boxtext {
position: absolute;
top: 50%;
left: 0;
width: 300rpx;
height: 300rpx;
font-size: 12px;
}
.dk-text {
margin: 30rpx 10rpx;
}
.map {
width: 100%;
height: 560rpx;
margin-top: 20rpx;
}
@keyframes turn {
100% {
transform: rotate(-360deg)
}
}
// index.js
const {
distanceOf,
randId
} = require("../../utils/util")
var QQMapWX = require("../../utils/qqmap-wx-jssdk/qqmap-wx-jssdk")
var qqmapwx;
let marker = []
Page({
data: {
targetLocation: [0, 0],
markers: [],
allowRange: 100,
userInfo: {
location: [],
userAddress: "",
dis: 0
}
},
onLoad() {
const _this = this
qqmapwx = new QQMapWX({
key: "key"
})
qqmapwx.geocoder({
address: "北京天安门",
success: function (res) {
_this.setData({
targetLocation: res.result.location
})
_this.addMark(res.result.location.lng, res.result.location.lat, "北京天安门")
_this.getUserLocation()
}
})
},
getUserLocation() {
const _this = this
wx.getLocation({
type: 'gcj02', // 腾讯地图的坐标系采用的gcj02
success: function (res) {
console.log(res)
_this.setData({
["userInfo.location"]: [res.latitude, res.longitude]
})
_this.addMark(res.longitude, res.latitude, "我")
const dis = distanceOf({
"x": _this.data.targetLocation.lng,
"y": _this.data.targetLocation.lat
}, {
"x": res.longitude,
"y": res.latitude
})
qqmapwx.reverseGeocoder({
location: {
latitude: res.latitude,
longitude: res.longitude
},
success(resp) {
_this.setData({
["userInfo.address"]: resp.result.address,
["userInfo.dis"]: dis
})
}
})
}
})
},
addMark(lng, lat, name, ) {
marker.push({
id: randId(), //标记点 id
width: 50,
height: 50,
longitude: lng,
latitude: lat,
label: {
content: name,
color: '#f00',
textAlign: "center",
fontSize: 12
},
callout: {
content: '气泡',
color: "#f00",
fontSize: 30
},
})
this.setData({
markers: marker
})
},
bindClock() {
wx.showToast({
title: '外勤打卡',
})
},
fun() {}
})
结语
到此就结束了,首次写如有不对,请留下您的建议