1. 程式人生 > 實用技巧 >微信小程式地圖獲取地點資訊(打卡簽到功能為例)-2020-7-26

微信小程式地圖獲取地點資訊(打卡簽到功能為例)-2020-7-26

目錄

微信小程式地圖獲取地點資訊(打卡簽到功能為例)

解決方案:利用微信小程式的地圖元件獲取到使用者的地理位置資訊(經緯度),再通過騰訊地圖 SDK 獲取到對應的地理位置(即地名)

效果圖

  • 地圖已打馬賽克

前提步驟

首先需要了解的

程式碼部分

配置性程式碼

app.js 部分關鍵程式碼

  • key 需要換成你自己申請的
//app.js
// 引入SDK核心類
var QQMapWX = require('/utils/qqmap-wx-jssdk.min.js')

App({
  globalData: {
    // ..其他全域性變數..
    patrolForm: null,
      
    // 例項化API核心類
    qqmapsdk: new QQMapWX({
      key: '這個key是你申請下來的key' // 必填
    }),
      
    // ..其他全域性變數..
  },
  // 其他程式碼
})

app.json 部分關鍵程式碼(permission那個物件)

{
  "pages":[
    "pages/location_check_in/location_check_in"
  ],
  "window":{
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#3db0fc",
    "navigationBarTitleText": "WeChat",
    "navigationBarTextStyle": "white"
  },
  "style": "v2",
  "sitemapLocation": "sitemap.json",
  "permission": {
    "scope.userLocation": {
      "desc": "您的位置資訊將用於小程式簽到功能"
    }
  }
}

https://apis.map.qq.com 新增到小程式後臺-開發-開發設定-伺服器域名中

  • 這個操作需要小程式管理員進到後臺去配置
  • 我們只需要在開發工具右上角 詳情-本地設定 勾上 不校驗合法域名........ 即可繼續開發

功能性程式碼

頁面程式碼:location_check_in.wxml

<!--location_check_in/location_check_in.wxml-->
<view class="wholeContinaer">
	<map id="myMap" markers="{{markers}}" style="width:100%;height:100vh;" longitude="{{poi.longitude}}" latitude="{{poi.latitude}}" scale='16' show-location>
	</map>

	<view class="checkInPanel">
		<!-- <view class="checkInBtn" bindtap="checkIn" style="background:url('../../images/zcxj/checkInBj.png') center / contain no-repeat"> -->
		<view class="checkInBtn {{canClick ? '' : 'disableClick'}}" bindtap="checkIn">
			<view class="checkInTitle">簽到</view>
			<view class="checkInTime">{{time}}</view>
		</view>
		<!-- <view class="whitePositionPanel" style="background:url('../../images/zcxj/jxk.png') center / contain no-repeat"> -->
		<view class="whitePositionPanel">
			<view class="positonTextRow">
				<image class="positionIcon" src="../../images/zcxj/positionIcon.png"></image>
				<view class="positionFont">{{addressName}}</view>
			</view>
		</view>
		<view class="rePosition" bindtap="rePosition">
			<image class="positionIcon" src="../../images/zcxj/rePosition.png"></image>
			<view class="positionFont">重新定位</view>
		</view>
	</view>
</view>

樣式程式碼:location_check_in.wxss

/* location_check_in/location_check_in.wxss */
Page{
  background-color: #f2f2f2;
}
.wholeContinaer{
  position: relative;
  height: 100vh;
}

.mapContianer{
  background-color: turquoise;
  width: 100vw;
  height: 100vh;
}

.checkInPanel{
  position: absolute;
  width: 705rpx;
  height: 520rpx;
  bottom: 25rpx;
  left: 25rpx;
  /* background-color: #ffffff; */
}
.checkInBtn{
  width: 280rpx;
  height: 280rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  position: absolute;
  left: calc(50% - 140rpx);
  z-index: 12;

  border-radius: 50%;
  background-image: linear-gradient(180deg, 
      #00a0e9 0%, 
      #0095e9 73%, 
      #0089e9 100%);
  box-shadow: 0 0 10rpx 0rpx #0089e9;
  /* margin: 0 auto; */
}
.disableClick{
  pointer-events: none;
}
.checkInTitle{
  font-size: 36rpx;
  line-height: 34rpx;
  color: #ffffff;
}
.checkInTime{
  font-size: 24rpx;
  line-height: 34rpx;
  color: #8cd7fe;
  margin-top: 10rpx;
}

.whitePositionPanel{
  width: 100%;
  height: 412rpx;
  position: absolute;
  bottom: 0rpx;

  background-color: #ffffff;
  border-radius: 10rpx;
  
  display: flex;
  align-items: center;
  justify-content: center;
}

.positonTextRow{
  display: flex;
  align-items: center;
  justify-content: center;
  margin-top: 80rpx;
}
.positonTextRow .positionIcon{
  width: 20rpx;
  height: 26rpx;
  margin-right: 10rpx;
}
.positonTextRow .positionFont{
  font-size: 22rpx;
  line-height: 29rpx;
  color: #9c9c9c;
}

.rePosition{
  width: 130rpx;
  height: 35rpx;
  background-color: #ffffff;
  border-radius: 10rpx;
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 60rpx;
}
.rePosition .positionIcon{
  width: 24rpx;
  height: 24rpx;
  margin-right: 10rpx;
}
.rePosition .positionFont{
  font-size: 18rpx;
  color: #333333;
  line-height: 35rpx;
}

邏輯程式碼:location_check_in.js

  • 逆地址解析(座標位置描述)函式官方文件:reverseGeocoder(options:Object)
  • realyCheckIn 函式為業務邏輯程式碼,此前已經獲取到了地理位置,缺少了部分前置業務程式碼,會導致程式碼報錯,改成你自己的就好
// location_check_in/location_check_in.js
const util = require('../../utils/util')
const app = getApp()
const urlList = require("../../utils/api.js")  // 根據實際專案自己配置

// 例項化API核心類
const qqmapsdk = app.globalData.qqmapsdk

Page({

  /**
   * 頁面的初始資料
   */
  data: {
    markers: '',
    poi: {
      latitude: '',
      longitude: ''
    },
    addressName: '',
    time: '',
    timer: '',
    timer2: '',  // 用來每個一段時間自動重新整理一次定位
    canClick: true
  },
 
  getAddress(e) {
    var that = this;
    qqmapsdk.reverseGeocoder({
      //位置座標,預設獲取當前位置,非必須引數
      /**
       * 
        location: {
          latitude: 39.984060,
          longitude: 116.307520
        },
      */
      // 成功後的回撥
      success: function(res) {
        // console.log(res);
        that.setData({
          addressName: res.result.address
        })
        var res = res.result;
        var mks = [];
        //當get_poi為0時或者為不填預設值時,檢索目標位置,按需使用
        mks.push({ // 獲取返回結果,放到mks陣列中
          title: res.address,
          id: 0,
          latitude: res.location.lat,
          longitude: res.location.lng,
          iconPath: '../../images/zcxj/myPosition.png', // 圖示路徑
          width: 21,
          height: 28,
          // callout: { //在markers上展示地址名稱,根據需求是否需要
          //   content: res.address,
          //   color: '#000',
          //   display: 'ALWAYS'
          // }
        });
        that.setData({ // 設定markers屬性和地圖位置poi,將結果在地圖展示
          markers: mks,
          poi: {
            latitude: res.location.lat,
            longitude: res.location.lng
          }
        });
      },
      fail: function(error) {
        console.error(error);
      },
      complete: function(res) {
        console.log(res);
      }
    })
  },
  getTime: function () {
    let that = this
    let time = that.data.time
    that.setData({
      timer: setInterval(function () {
        time = util.formatTime(new Date())
        that.setData({
          time: time.substr(-8)
        });
        if (time == 0) {
          // 頁面跳轉後,要把定時器清空掉,免得浪費效能
          clearInterval(that.data.timer)
        }
      }, 1000)
    })
  },
  rePosition: function () {
    console.log('使用者點了重新定位')
    this.getAddress()
  },
  checkIn: function () {
    this.setData({
      canClick: false
    })
    console.log('使用者點選了簽到')

    
    var that = this
    var nowTime = util.formatTime(new Date())
    wx.showModal({
      title: '請確認打卡資訊',
      // content: '請確認待整改項已整改完畢!',
      content: `地點:${this.data.addressName}\n時間:${nowTime}`,  // 開發者工具上沒有換行,真機除錯時會有的
      confirmText: '確認',
      success (res) {
        if (res.confirm) {
          console.log('使用者點選確定')
          // 調起簽到介面
          that.realyCheckIn()
          
        } else if (res.cancel) {
          console.log('使用者點選取消')
          that.setData({
            canClick: true
          })
        }
      }
    })
  },
  realyCheckIn: function() {
    var that = this
    var patrolForm = app.globalData.patrolForm  // 其他需要一併提交過去的業務資料

    console.log(app.globalData)
    // debugger
    // 要在這裡給 patrolForm 補充其他的引數
    patrolForm.checkaddress = this.data.addressName
    patrolForm.searchtime = util.formatTime(new Date())
    // 應該先判斷使用者有沒有登入,沒登入就授權登入
    patrolForm.searchuser = app.globalData.user ? app.globalData.user.UserName : app.globalData.userInfo.nickName
    console.log("傳給後臺的 searchuser:", patrolForm.searchuser)
    // 拼接:"經度,緯度"
    patrolForm.latandlon = this.data.poi.longitude + "," + this.data.poi.latitude
    

    console.log(patrolForm)
    console.log("↑ 簽到提交的post引數")

    var tmpNumber = 0
    wx.request({
      url: urlList.submitCheckInInfo,
      data: patrolForm,
      method: "POST",
      header: {
        'content-type': 'application/x-www-form-urlencoded'
      },
      success: function (res) {
        console.log(res)
        if(res.data.IsSuccess) {
          console.log(res.data.IsSuccess, typeof(res.data.IsSuccess))
          console.log("請求成功")
          var patrolId = res.data.ReturnData[0].id
          // // 看怎麼取到返回的id
          // debugger

          if (patrolForm.img_arr1.length > 0) {
            for (var i = 0; i < patrolForm.img_arr1.length; i++){
              tmpNumber = i
              wx.uploadFile({
                // 圖片上傳的介面地址
                url: urlList.submitCheckInPhoto + "?patrolid=" + patrolId,
                filePath: patrolForm.img_arr1[i],
                name: 'content',
                // formData: {
                //   // 這裡面可以攜帶一些引數一併傳過去
                //   patrolId: patrolId
                // },
                // header: {
                //   Authorization: token
                // },
                success: function (res) {
                  console.log(res)
                },
                fail: function (res) {
                  that.setData({
                    canClick: true
                  })
                },
                complete: function () {
                  // 因為上傳圖片是非同步操作,所以會導致這裡的 i 會取不到,故需要用個作用域更大點的變數來標識,否則 if 裡面的程式碼不會執行
                  if(tmpNumber === patrolForm.img_arr1.length - 1) {
                    // 有圖片就等圖片上傳完了再返回首頁
                    wx.showToast({
                      title: '巡查簽到成功!',
                      icon: 'success',
                      duration: 2000,
                      complete: function(){
                        wx.navigateBack({
                          delta: 2  // 回退兩層頁面
                        })
                      }
                    })
                  }
                }
              })
            }
          } else{
            wx.showToast({
              title: '巡查簽到成功!',
              icon: 'success',
              duration: 2000,
              complete: function(){
                wx.navigateBack({
                  delta: 2
                })
              }
            })
          }
        }
      },
      fail: function(res) {
        that.setData({
          canClick: true
        })
      }
    })

  },

  /**
   * 生命週期函式--監聽頁面載入
   */
  onLoad: function (options) {
    var that = this
    that.getTime()
    that.getAddress()
    
    that.setData({
      canClick: true, // 允許使用者點選,防止多次提交
      timer2: setInterval(function () {
        that.getAddress()
      }, 20000)  // 每20秒重新整理一次定位
    })
  },

  /**
   * 生命週期函式--監聽頁面解除安裝
   */
  onUnload: function () {
    clearInterval(this.data.timer)
    clearInterval(this.data.timer2)
    console.log("定時器已被清除")
  },

  /**
   * 生命週期函式--監聽頁面初次渲染完成
   */
  onReady: function () {

  },

  /**
   * 生命週期函式--監聽頁面顯示
   */
  onShow: function () {

  },

  /**
   * 生命週期函式--監聽頁面隱藏
   */
  onHide: function () {

  },

  /**
   * 頁面相關事件處理函式--監聽使用者下拉動作
   */
  onPullDownRefresh: function () {

  },

  /**
   * 頁面上拉觸底事件的處理函式
   */
  onReachBottom: function () {

  },

  /**
   * 使用者點選右上角分享
   */
  onShareAppMessage: function () {

  }
})

demo 下載

gitee地址:https://gitee.com/Suwanbin/positionCheckIn

如果對你有幫助,還請幫忙點個 star!