目前我们需要实现小程序打卡签到功能,那我们就需要腾讯地图组件获取到用户的地理位置信息(经纬度),再通过腾讯地图 SDK 获取到对应的地理位置
前期准备
当然在实现功能前,我们需要去开通对应账号这个看公司选择了,需要负责人创建对应账号,成功之后进入应用管理
如果要在小程序中实现地图功能需要开通webServiceAPI,直接选择,空白即可
保存之后,就可以参考微信小程序JavaScript SDK | 腾讯位置服务 在小程序中调用地图组件
- 我们需要下载 sdk,放在对应文件夹中,去引用它(
qqmap-wx-jssdk.min.js
)
代码部分
app.js 关键代码
// 2024 www.kingbal.com Inc. All rights reserved.
var QQMapWX = require('/utils/qqmap-wx-jssdk.min.js')
App({
globalData: {
qqmapsdk: new QQMapWX({
key: '申请下来的key'
}),
},
})
app.json 部分关键代码(permission那个对象)
{
"pages":[
...
],
"window":{
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#3db0fc",
"navigationBarTitleText": "WeChat",
"navigationBarTextStyle": "white"
},
"style": "v2",
"sitemapLocation": "sitemap.json",
"requiredPrivateInfos": [
"getLocation"
],
"permission": {
"scope.userLocation": {
"desc": "您的位置信息将用于小程序签到功能"
}
}
}
将 https://apis.map.qq.com
添加到小程序后台-开发-开发设置-服务器域名中
- 我们在本地在开发工具右上角 详情-本地设置 勾上 不校验合法域名........ 即可继续开发
功能性代码
check_in.json
{
"usingComponents": {
"van-dialog": "@vant/weapp/dialog/index"
},
"navigationBarBackgroundColor": "#F8F7FB",
"navigationBarTitleText": "签到"
}
check_in.wxml
<view>
<map id="myMap" markers="{{markers}}" circles="{{circles}}" style="width:100%;height:100vh;" longitude="{{checkInData.longitude}}" latitude="{{checkInData.latitude}}" scale='16' show-location>
</map>
<view class="check-in-info">
<view class="check-in-btn flex-center direction-column {{canClick ? '' : 'disableClick'}}" bindtap="onCheckIn">
<view class="check-in-title">签到</view>
<view class="check-in-time">{{time}}</view>
</view>
<view class="check-in-info-bg">
<view class="check-in-text-row">
<image class="check-in-icon" src="https://www.kingbal.com/yourpostion.png"></image>
<view class="check-in-font">{{checkInData.addressName}}</view>
</view>
</view>
<view class="re-postion" bindtap="rePosition">
<image class="re-postion-icon" src="https://www.kingbal.com/yourrepostion.png"></image>
<view class="re-postion-font">重新定位</view>
</view>
</view>
</view>
<van-dialog use-slot title="请确认打卡信息" show="{{ show }}" show-cancel-button bind:confirm="onConfirm" bind:cancel="onCancel" bind:getuserinfo="getUserInfo">
<view class="flex-center direction-column check-in-dialog">
<view>{{checkInData.addressName}}</view>
<view class="margin-top-10">{{checkInData.nowTime}}</view>
</view>
</van-dialog>
<van-dialog id="van-dialog" />
check_in.wxss
page {
font-family: PingFang SC-Regular, PingFang SC;
font-size: 24rpx;
background-color: #F8F7FB;
}
.flex {
display: flex;
}
.flex-center {
display: flex;
justify-content: center;
align-items: center;
}
.direction-column {
flex-direction: column;
}
.flex-start {
display: flex;
justify-content: flex-start;
align-items: center;
}
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
}
.flex-end {
display: flex;
justify-content: flex-end;
align-items: center;
}
.flex-around {
display: flex;
justify-content: space-around;
align-items: center;
}
.flex-start-base {
display: flex;
justify-content: flex-start;
align-items: baseline;
}
.voerflow {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
text-overflow: ellipsis;
overflow: hidden;
}
.margin-top-5 {
margin-top: 5rpx;
}
.margin-top-10{
margin-top: 20rpx;
}
.margin-top-20 {
margin-top: 20rpx;
}
.margin-top-50{
margin-top: 50rpx;
}
.margin-left-15{
margin-left: 25rpx;
}
.margin-left-5{
margin-left: 5rpx;
}
.padding-5{
padding: 5rpx;
}
.padding-20{
padding: 20rpx;
}
.main {
text-align: center;
justify-content: center;
}
.other-info{
width: 100%;
}
/** 内容**/
.other-info {
width: 702rpx;
background: #FFFFFF;
box-shadow: 0rpx 6rpx 12rpx 0rpx rgba(51, 51, 51, 0.05);
border-radius: 16rpx;
margin-top: 16rpx;
padding:20rpx;
}
.check-in-info{
position: absolute;
width: 705rpx;
height: 520rpx;
bottom: 25rpx;
left: 25rpx;
}
.check-in-info .check-in-btn{
width: 280rpx;
height: 280rpx;
align-items: center;
position: absolute;
left: calc(50% - 140rpx);
z-index: 12;
border-radius: 50%;
background-image: linear-gradient(180deg,
#fdb217 0%,
#fdb217 73%,
#fdb217 100%);
box-shadow: 0 0 10rpx 0rpx #fdb217;
}
.check-in-info .check-in-title{
font-size: 36rpx;
line-height: 34rpx;
color: #ffffff;
}
.check-in-info .check-in-time{
font-size: 24rpx;
line-height: 34rpx;
color: #ffffff;
margin-top: 10rpx;
}
.check-in-info .check-in-info-bg{
width: 100%;
height: 412rpx;
position: absolute;
bottom: 0;
background-color: #ffffff;
border-radius: 10rpx;
}
.check-in-info-bg .check-in-text-row{
display: flex;
align-items: center;
justify-content: center;
margin-top: 200rpx;
}
.check-in-info-bg .check-in-text-row .check-in-icon{
width: 60rpx;
height: 60rpx;
margin-right: 10rpx;
}
.check-in-info-bg .check-in-text-row .check-in-font{
font-size: 22rpx;
line-height: 29rpx;
color: #9c9c9c;
}
.check-in-info .re-postion{
width: 130rpx;
height: 35rpx;
background-color: #ffffff;
border-radius: 10rpx;
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top:60rpx;
}
.re-postion .re-postion-icon{
width: 24rpx;
height: 24rpx;
margin-right: 10rpx;
}
.check-in-dialog{
height: 280rpx;
}
check_in.js
// 2024 www.kingbal.com Inc. All rights reserved.
const app = getApp()
const qqmapsdk = app.globalData.qqmapsdk
const util = require('../../utils/util')
Page({
data: {
markers: '',
checkInData: {
latitude: '',
longitude: '',
addressName: '',
nowTime: '',
},
time: '',
timer: '',
timer2: '',
canClick: true
},
getAddress:function(e) {
let _this = this;
var checkInData = _this.data.checkInData;
qqmapsdk.reverseGeocoder({
success: function(res) {
checkInData.addressName = res.result.address
var res = res.result;
checkInData.latitude = res.location.lat,
checkInData.longitude = res.location.lng,
_this.setData({
checkInData: checkInData,
markers: [{
title: res.address,
id: 0,
latitude: res.location.lat,
longitude: res.location.lng,
iconPath: 'https://www.kingbal.com/mini/yourpostion.png',
width: 28,
height: 28,
}],
circles: [{
latitude: res.location.lat,
longitude: res.location.lng,
color: '#FF0000DD',
fillColor: '#7cb5ec88',
radius: 200, //指定距离范围
strokeWidth: 1
}]
});
},
fail: function(error) {
console.error(error);
},
complete: function(res) {
console.log(checkInData);
}
})
},
getTime: function () {
let _this = this
let checkInData = _this.data.checkInData
_this.setData({
timer: setInterval(function () {
checkInData.nowTime = util.formatTime(new Date())
checkInData.nowTime = checkInData.nowTime.substr(-8)
_this.setData({
checkInData:checkInData
});
if (checkInData.nowTime == 0) {
clearInterval(_this.data.timer)
}
}, 1000)
})
},
rePosition: function () {
console.log('用户点了重新定位')
this.getAddress()
},
onCheckIn: function () {
this.setData({
canClick: false,
show:true
})
} ,
onCancel:function() {
let _this = this;
_this.setData({ show: false, canClick: true });
},
onConfirm:function() {
let _this = this;
_this.submitCheckIn()
_this.setData({ show: false });
},
submitCheckIn: function() {
let _this = this
let checkInData = _this.data.checkInData
console.log(checkInData)
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
let _this =this;
_this.getTime()
_this.getAddress()
_this.setData({
canClick: true, // 允许用户点击,防止多次提交
timer2: setInterval(function () {
_this.getAddress()
}, 20000) // 每20秒刷新一次定位
})
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
clearInterval(this.data.timer)
clearInterval(this.data.timer2)
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
utils > util.js
// 2024 www.kingbal.com Inc. All rights reserved.
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : `0${n}`
}
const formatDate = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
return [year, month, day].map(formatNumber).join('-')
}
module.exports = {
formatTime: formatTime,
formatDate: formatDate
}
最终效果: