Bootstrap

微信小程序:地图获取地点信息及打卡签到、显示范围

目前我们需要实现小程序打卡签到功能,那我们就需要腾讯地图组件获取到用户的地理位置信息(经纬度),再通过腾讯地图 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
}

最终效果:

;