Summary of the work of wechat small program based on positioning to achieve the punch card function
Recently, a small task of my work is to realize a function similar to enterprise wechat to clock in and out of work in wechat mini program, and the main front-end work is to calculate location distance
1. Add the longitude and latitude of the store
First we need to add the longitude and latitude of the store
To add longitude and latitude, we can use a small program map plug-in provided by Tencent. First of all, log in the micro channel public number small program background, in the “Settings” column of “third-party Settings” at the bottom of a “plug-in management”, where you can choose to add plug-ins
Search for “Map selection” in the add plugin popup
Then choose to add “Tencent location service map selection” small program plug-in
Then click on the plugin details, which contains the development documentation, with detailed instructions on how to use this map selection
After all the configuration is complete, open the map selection plug-in in the small program and the following interface will appear
So far we have completed the key step of adding the longitude and latitude of the store
2. Obtain position positioning in wechat mini program
wx.getLocation(Object object)
wx.getLocation({
type: 'wgs84',
success (res) {
const latitude = res.latitude
const longitude = res.longitude
const speed = res.speed
const accuracy = res.accuracy
}
})
Copy the code
The API provided by this wechat small program only gets longitude and latitude. If we want to know the specific information of the current location, for example, XX province, XX City, XX street, we also need to use the SDK provided by Tencent location service to perform parsing
3. Register Tencent location service account, configure information, and download SDK
First of all, we have to go to the official website of Tencent Location service to register an account of Tencent location service
Console –> My App –> Create App –> Fill in the name and category
Add key –> Check WebServiceAPI –> Check wechat applet –> Fill in your applet APPID –> Copy key (this is very important to use applet)
Head navigation –> Development Document –> wechat applets –> wechat applets JavaScript SDK
Then there are details about the micro channel small program location analysis of the relevant operations and code examples
Afraid of the picture is not too clear, the main I or excerpt listed
-
Apply for developer key: Apply for a key
-
To enable the webserviceAPI service, choose Application Management > My App > Add Key > Select webserviceAPI > Save
(The small program SDK needs to use some services of webserviceAPI, so the KEY to use this function needs to have corresponding permissions.)
-
Download JavaScriptSDK, JavaScriptSDK v1.1, JavaScriptSDK v1.2
-
Set the secure domain name, in the small program management background -> Development -> Development Management -> Development Settings -> “Server Domain name” set the request legitimate domain name, add apis.map.qq.com
-
Applets example
// Introduce SDK core classes, js files according to their own business, location can be placed by themselves
var QQMapWX = require('.. /.. /libs/qqmap-wx-jssdk.js');
var qqmapsdk;
Page({
onLoad: function () {
// Instantiate the API core class
qqmapsdk = new QQMapWX({
key: 'Application key'
});
},
onShow: function () {
// Call the interface
qqmapsdk.search({
keyword: 'hotel'.success: function (res) {
console.log(res);
},
fail: function (res) {
console.log(res);
},
complete: function (res) {
console.log(res); }}); }})Copy the code
4. Key code implementation of latitude and longitude analysis
globalData = {
getLocation: function () {
return new Promise((resolve, reject) = > {
// Instantiate the API core class
const qqmapsdk = new QQMapWX({
key: 'xxxxx'}); wx.getLocation({type: 'gcj02'.// Returns the latitude and longitude that can be used for wx.openLocation
success(res) {
const latitude = res.latitude;
const longitude = res.longitude;
qqmapsdk.reverseGeocoder({
location: {
latitude,
longitude,
},
success(res) {
constlocationData = { ... res.result.address_component, latitude, longitude, };// Redux's data warehouse state management is used here
store.dispatch({
type: action.SET_CURRENT_LOACTION,
currentLocation: locationData,
});
resolve(locationData);
},
fail: function (error) {
console.error(error);
reject('Latitude and longitude resolution failed');
},
complete: function (res) {
console.log(res); }}); },fail: function (error) {
console.error(error); reject( failAuthDenyLocationEnum.FAIL_AUTH_DENY_LOCATION ); }}); }); }};Copy the code
Analytical results of normal latitude and longitude:
5. Get the latitude and longitude of the two points and calculate the distance
This is baidu code.
// Calculate the distance with the latitude and longitude of the first point respectively; The second point latitude, longitude
getDistance(lat1,lng1,lat2,lng2){
// Convert latitude and longitude to distance
function rad(d){
return d * Math.PI / 180.0;// Convert latitude and longitude to trigonometric form.
}
const radLat1 = rad(lat1);
const radLat2 = rad(lat2);
const a = radLat1 - radLat2;
const b = rad(lng1) - rad(lng2);
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
s = s *6378.137 ;
console.log('s', s)
// The output is km
s = Math.round(s * 10000) / 10000;
// The output is meters
// s = Math.round(s * 10000000);
// s = s.toFixed(4);
return s;
}
Copy the code
6. Is it within the range of the punch card
countDistance() {
if(!this.shopLat || !this.shopLng){
this.locationInfo = 'The longitude and latitude Settings of the store are wrong, so it cannot be punched in'
this.disableClockIn = true
this.$apply();
return
}
if(!this.userLat || !this.userLng){
this.locationInfo = 'User location error'
this.disableClockIn = true
this.$apply();
return
}
this.distance = this.getDistance(this.userLat, this.userLng, this.shopLat, this.shopLng)
if(this.distance <= this.distanceClockIn){
this.locationInfo = 'You are in the clock range'
this.disableClockIn = false
}
if(this.distance > this.distanceClockIn){
this.locationInfo = 'You are out of range'
this.disableClockIn = true
}
this.$apply();
}
Copy the code
7. Monitor position changes in real time
wx.getSetting({
success(res) {
if(! res.authSetting['scope.userLocation']) {
_this.locationInfo = 'You have refused to authorize location information'
_this.failAuthDenyLocation = true
_this.$apply()
} else {
// Calculate the distance every 10 seconds using wx.getLocation for now. Using wx.onLocationChange to listen for location changes is problematic
_this.timer = setInterval(() = > {
_this.getLocation().then(() = > {
_this.countDistance()
console.log('timer-distance', _this.distance)
}).catch(err= > console.log(err))
}, 10000); }}})Copy the code
// Clear the timer when the page unloads
onUnload() {
clearInterval(this.timer)
}
Copy the code
At this point on the micro channel small program according to the positioning of the key steps to achieve the punch card function have been completed
8. Business process code
Finally attached is the business process code for this punch in function. I used WEpy
import wepy from 'wepy';
import { connect } from 'wepy-redux';
import util from '.. /.. /utils/util';
import api from '.. /.. /utils/api';
import { failAuthDenyLocationEnum } from '.. /.. /utils/constant';
@connect({
userInfo(state) {
return state.user.userInfo;
},
currentLocation(state) {
return state.user.currentLocation;
},
okUser(state) {
returnstate.user.ok; }})export default class ClerkClockIn extends wepy.page {
config = {
navigationBarTitleText: 'Shop assistant closes shift'.navigationBarBackgroundColor: '#EA1717'.navigationBarTextStyle: 'white'}; components = { }; mixins = []; data = {client: {},
key: ' '.nowTime: ' '.timer: null.shopLat: ' '.shopLng: ' '.userLat: ' '.userLng: ' '.distance: ' '.locationInfo: ' '.disableClockIn: true.distanceClockIn: 3.// Clocking distance 1 means one kilometer
failAuthDenyLocation: false.// Whether to reject authorization location information
};
computed = {};
methods = {
clerkClockIn() {
if(!this.disableClockIn){
if(this.clerkPrisonLogData) {
api.shop.clerkPrisonLogOut({shopId: this.shopId}).then(r= > {
if(r.status === 'OK'){
util.toast('Clocked in successfully')
setTimeout(() = > {
this.query()
}, 500)
}
}).catch(err= > console.log(err))
}else{
api.shop.clerkPrisonLogIn({shopId: this.shopId}).then(r= > {
if(r.status === 'OK'){
util.toast('Clocked in successfully')
setTimeout(() = > {
this.query()
}, 500)
}
}).catch(err= > console.log(err))
}
}
},
// Obtain authorization again
openConfirm: function () {
wx.showModal({
content: 'Detect that you do not have location permission on this applet, do you want to set it to open? '.confirmText: "Confirm".cancelText: "Cancel".success: function (res) {
console.log(res);
// Click "OK" to open the Settings page
if (res.confirm) {
console.log('User clicks OK')
wx.openSetting({
success: (res) = >{}})}else {
console.log('User hit Cancel')}}})},}; watch = {}// Calculate the distance with the latitude and longitude of the first point respectively; The second point latitude, longitude
getDistance(lat1,lng1,lat2,lng2){
// Convert latitude and longitude to distance
function rad(d){
return d * Math.PI / 180.0;// Convert latitude and longitude to trigonometric form.
}
const radLat1 = rad(lat1);
const radLat2 = rad(lat2);
const a = radLat1 - radLat2;
const b = rad(lng1) - rad(lng2);
let s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a/2),2) +
Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/2),2)));
s = s *6378.137 ;
console.log('s', s)
// The output is km
s = Math.round(s * 10000) / 10000;
// The output is meters
// s = Math.round(s * 10000000);
// s = s.toFixed(4);
return s;
}
// Is it within the range of the clock
countDistance() {
if(!this.shopLat || !this.shopLng){
this.locationInfo = 'The longitude and latitude Settings of the store are wrong, so it cannot be punched in'
this.disableClockIn = true
this.$apply();
return
}
if(!this.userLat || !this.userLng){
this.locationInfo = 'User location error'
this.disableClockIn = true
this.$apply();
return
}
this.distance = this.getDistance(this.userLat, this.userLng, this.shopLat, this.shopLng)
if(this.distance <= this.distanceClockIn){
this.locationInfo = 'You are in the clock range'
this.disableClockIn = false
}
if(this.distance > this.distanceClockIn){
this.locationInfo = 'You are out of range'
this.disableClockIn = true
}
this.$apply();
}
getLocation() {
return new Promise((resolve, reject) = > {
this.$parent.globalData.getLocation().then(({latitude, longitude}) = > {
if(latitude && longitude){
this.userLat = latitude
this.userLng = longitude
this.failAuthDenyLocation = false
this.$apply()
resolve()
}
}).catch(err= > {
console.log(err)
if(err === failAuthDenyLocationEnum.FAIL_AUTH_DENY_LOCATION){ } reject(err) }); })}// Monitor position changes in real time
onShow() {
this.getLocation().then(() = > {
this.countDistance()
}).catch(err= > console.log(err))
const _this = this
wx.getSetting({
success(res) {
if(! res.authSetting['scope.userLocation']) {
_this.locationInfo = 'You have refused to authorize location information'
_this.failAuthDenyLocation = true
_this.$apply()
} else {
// Calculate the distance every 10 seconds using wx.getLocation for now. Using wx.onLocationChange to listen for location changes is problematic
_this.timer = setInterval(() = > {
_this.getLocation().then(() = > {
_this.countDistance()
console.log('timer-distance', _this.distance)
}).catch(err= > console.log(err))
}, 10000); }}})this.$apply();
}
onReady() {
api.common.queryClientInfo().then((r) = > {
this.client = r;
this.$apply();
});
}
//
onLoad(options) {
console.log('currentLocation'.this.currentLocation)
this.shopId = options.shopId ? Number(options.shopId) : ' '
this.shopLat = options.shopLat ? Number(options.shopLat) : ' '
this.shopLng = options.shopLng ? Number(options.shopLng) : ' '
this.userLat = this.currentLocation.latitude
this.userLng = this.currentLocation.longitude
this.$apply();
}
onUnload() {
clearInterval(this.timer)
}
onShareAppMessage(rest){}}Copy the code