uniapp h5 位置選擇,微信定位+騰訊位置服務獲取當前地址,逆地址解析

一、獲取當前地理座標

首先引入JSSDK

npm install jweixin-module --save  

使用

var jweixin = require('jweixin-module')  
jweixin.ready(function(){  
    // TODO  
});  

DCloud官網的論壇,有分享的例子http://ask.dcloud.net.cn/article/36007。

 

我這裏做個定位接口例子。

首先要看微信的文檔。清楚大致的流程。https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115

1、common目錄,創建文件,名稱是wechat.js。內容如下:

   注意要點:

1、前端域名要放在微信公衆平臺js安全域名下。

2、 url:(window.location.href).split('#')[0]  當前頁面url作爲參數 進行數字簽名。

// import request from './request'; 
var jweixin = require('jweixin-module');
import store from '@/store'
import api from '@/common/vmeitime-http/' //自己封裝的網絡請求類,也可以直接使用uni.request 

export default {
    //判斷是否在微信中  
    isWechat: function() {
        var ua = window.navigator.userAgent.toLowerCase();
        if (ua.match(/micromessenger/i) == 'micromessenger') {
            // console.log('是微信客戶端')
            return true;
        } else {
            // console.log('不是微信客戶端')
            return false;
        }
    },
    //初始化sdk配置  
    initJssdkShare: function(callback, url) {
        //服務端進行簽名 ,可使用uni.request替換。 簽名算法請看文檔  
        post(
            'https://fbyc.microchainsoft.cn/index/wechat/getSignPackage',
            {
                url: url
            },
            function(res) {
                // console.log(res)
                if (res.data) {
                    jweixin.config({
                        debug: true,
                        appId: res.data.appId,
                        timestamp: res.data.timestamp,
                        nonceStr: res.data.nonceStr,
                        signature: res.data.signature,
                        jsApiList: [
                            'checkJsApi',
                            'onMenuShareTimeline',
                            'onMenuShareAppMessage',
                            'getLocation'
                        ]
                    });
                    //配置完成後,再執行分享等功能  
                    if (callback) {
                        callback(res.data);
                    }
                }
        });
    },
    initJssdk:function(callback){
		
		api.getAddressCoordinate({
				appId:uni.getStorageSync('hmAppId'),
				url:(window.location.href).split('#')[0]
			}).then((res)=>{
				if(res.data){
					console.log(".data===="+JSON.stringify(res.data))
					console.log(".data.data===="+JSON.stringify(res.data.data))
				    jweixin.config({
				        debug: false,
				        appId: res.data.data.appId,
				        timestamp: res.data.data.timestamp,
				        nonceStr: res.data.data.nonceStr,
				        signature: res.data.data.signature,
				        jsApiList: [
				            'checkJsApi',
				            'getLocation'
				        ]
				    });
				    //配置完成後,再執行分享等功能  
				    if (callback) {
				        callback(res.data);
				    }
				}
				}).catch((err) => {
						console.log("微信signature失敗"+err)
				})
    },
    //在需要自定義分享的頁面中調用  
    share: function(data, url) {
        url = url ? url : window.location.href;
        if (!this.isWechat()) {
            return;
        }
        //每次都需要重新初始化配置,纔可以進行分享  
        this.initJssdkShare(function(signData) {
            jweixin.ready(function() {
                var shareData = {
                    title: data && data.title ? data.title : signData.site_name,
                    desc: data && data.desc ? data.desc : signData.site_description,
                    link: url,
                    imgUrl: data && data.img ? data.img : signData.site_logo,
                    success: function(res) {
                        //用戶點擊分享後的回調,這裏可以進行統計,例如分享送金幣之類的  
                        // post('/api/member/share');
                    },
                    cancel: function(res) {}
                };
                //分享給朋友接口  
                jweixin.onMenuShareAppMessage(shareData);
                //分享到朋友圈接口  
                jweixin.onMenuShareTimeline(shareData);
            });
        }, url);
    },
    //在需要定位頁面調用
    location: function(callback) {
        if (!this.isWechat()) {
            console.log('不是微信客戶端')
            return;
        }
        console.info('定位')
        this.initJssdk(function(res) {
            jweixin.ready(function() {
                console.info('定位ready')
                jweixin.getLocation({
                    type: 'gcj02', // 默認爲wgs84的gps座標,如果要返回直接給openLocation用的火星座標,可傳入'gcj02'
                    success: function (res) {
                        // console.log(res);
                        callback(res)
                    },
                    fail:function(res){
                        console.log(res)
                    },
                    // complete:function(res){
                    //     console.log(res)
                    // }
                });
            });
        });
    }
}

 2、main.js加載該文件

// #ifdef H5  
import wechat from './common/util/wechat'
if(wechat.isWechat()){
    Vue.prototype.$wechat =wechat;
}
// #endif

3、頁面中使用 

// #ifdef H5
            //獲取定位經緯度
            if (this.$wechat && this.$wechat.isWechat()) {
                 this.$wechat.location(function (res) {
                     console.log(res)
                    // let latitude = res.latitude; // 緯度,浮點數,範圍爲90 ~ -90
                    // let longitude = res.longitude; // 經度,浮點數,範圍爲180 ~ -180。
                    // todo
                    let latitude = 31.14979;
                    let longitude = 121.12426; 
                    
                    //根據經緯度,解析區域,提示用戶輸入
                 });
            }
            // #endif

 

 

二、逆地址解析

1、騰訊位置服務申請 服務調用前提 KEY

2、引入vue-jsonp 解決騰訊位置服務跨域請求問題

npm install vue-jsonp --save  

使用

import VueJsonp from 'vue-jsonp'

Vue.use(VueJsonp)

調用

this.$jsonp(url,{
                          key: this.publicKey,
                          location: locationObj
                        }).then(e => {
                            res(e.result);
                        })
                        .catch(err => {
                            res(err);
                        })

3、引入mimap組件 https://ext.dcloud.net.cn/plugin?id=1448

qqmap-wx-jssdk.min.js 可從微信下載

<template>
	<view class="server-place">
		<map
			id='map'
			ref='map'
			v-bind:style="{height: mapH + 'px'}"
			style="width: 100%;" 
			:latitude="latitude" 
			:longitude="longitude"
			:controls='controls'
			@regionchange='mapChange'>
		</map>
		
		<view class="map-tools">
			
			<view class="my-location" @click.stop="toMyLocation">
				<image class="left" src="/static/img/areame.png" mode=""></image>
				<view class="right">
					<text class="title">我的位置</text>
					<text class="text">{{myAddress}}</text>
				</view>
			</view>
			
			<view class="start-place">
				<view class="place">
					<text class="title">{{tipText}}</text>
					<text class="text">{{addressObj.address.formatted_addresses.recommend}}</text>
				</view>
				<view class="tip">{{descText}}</view>
				<button @click.stop="submitAdress" class="sure" type="primary">確認選擇</button>
			</view>
		</view>
	</view>
	
</template>

<script>
	var jweixin = require('jweixin-module');
	const app = getApp()
	var QQMapWX = require('./qqmap-wx-jssdk.min.js')
	var qqmapsdk = new QQMapWX({
	  key: 'LXCBZ-NNIKD-UZ64F-H6AFI-UNJLH-OCFGE' //app的key
	})
	// 'YVEBZ-JS7LF-PK2JW-JJNFX-BITHO-ATB57'
	export default {
		props: {
			tipText: {
				type: String,
				default: '選擇位置'
			},
			descText: {
				type: String,
				default: '使用當前定位或在地圖上標記位置'
			},
		},
		data() {
			return {
				publicKey:'',// h5的key
				mapH: 0,             // 地圖高度,可在initMapH()中設置高度
				longitude: 0,        // 初始經度
				latitude: 0,         // 初始緯度
				myAddress: '',   	 // 初始地址信息
				addressObj: {        // 地圖選點信息
					longitude: '',
					latitude: '',
					address: {
						address:'',
						formatted_addresses:{
							recommend:'請選擇位置'
							}
						}
					
					
				},
				controls: [           // 地圖中心點圖標, 可更換iconPath, 詳情見官方文檔關於map組件的介紹
					{
						iconPath: '/static/img/areacenter.png',
						position: { 
							// left: 175,
							left: window.screen.width/2-20,
							top: 210,
							width: 40, 
							height: 40,
						},
						clickable: false
					}
				],
			};
		},
		mounted() {
			let _this = this
			_this.$api.getAddressKey({
				appId: uni.getStorageSync('hmAppId'),
			}).then(res=>{
				if(res.data.code == 10000){
					_this.publicKey=res.data.data.key;
					this.getLocation()
					this.initMapH()
				}
			}).catch(res=>{
				console.error("查詢key失敗: " + JSON.stringify(res));
			})
		},
		methods:{
			// 查詢現在的位置
			getLocation() {
				let this_ = this
				 if (this.$wechat && this.$wechat.isWechat()) {
					this.$wechat.location(function (res) {
						console.log(res)
						let latitude = res.latitude; // 緯度,浮點數,範圍爲90 ~ -90
						let longitude = res.longitude; // 經度,浮點數,範圍爲180 ~ -180。
						let res2={
								latitude: latitude ,
								longitude: longitude
							}
							this_.initMap(res2)
						
						//根據經緯度,解析區域,提示用戶輸入
					});
				}else{
					console.error("不在微信環境中")
				}
			},
			
			// 初始化我的位置
			async initMap(res) {
				this.longitude = res.longitude;
				this.latitude = res.latitude;
				
				this.addressObj = Object.assign({}, this.addressObj,{
					longitude: res.longitude,
					latitude: res.latitude,
					address: await this.getAddressName(res)
				})
				this.myAddress = this.addressObj.address.formatted_addresses.recommend
			},
			
			// 地圖選擇位置後 查詢地點名稱
			async checkMap(res) {
				this.addressObj = Object.assign({}, this.addressObj,{
					longitude: res.longitude,
					latitude: res.latitude,
					address: await this.getAddressName(res)
				})
				console.log('當前位置:' + res.latitude + '|' + res.longitude);
			},
			
			// 監聽地圖位置變化
			mapChange(e) {
				let that = this
				clearTimeout(this.timer)
				this.timer = setTimeout(() => {
					if (e.type == 'end') {
						that.mapCtx = uni.createMapContext('map', this)
						that.mapCtx.getCenterLocation({
							success: res => {
								this.checkMap(res)
							},
							fail: err => {
								console.log(err);
							}
						})
					}
				}, 200)
			},
			// 查詢地圖中心點的名稱
			getAddressName(addressObj) {
				
				return new Promise((res) => {
					// #ifdef APP-PLUS
						qqmapsdk.reverseGeocoder({
							location: {
								latitude: addressObj.latitude,
								longitude: addressObj.longitude
							},
							get_poi: 1,
							poi_options: "page_size=1;page_index=1",
							output: 'jsonp',
							success: (e) => {
								res(e.result.formatted_addresses.recommend);
							},
							fail: err => {
								res(err);
							}
						})
					// #endif
					
					// #ifndef APP-PLUS
						// ======================== jsonp跨域 ======================== 
						let locationObj = addressObj.latitude+','+addressObj.longitude
						let url = 'https://apis.map.qq.com/ws/geocoder/v1?coord_type=5&get_poi=1&output=jsonp&poi_options=page_size=1;page_index=1';
						this.$jsonp(url,{
						  key: this.publicKey,
						  location: locationObj
						}).then(e => {
							res(e.result);
						})
						.catch(err => {
							res(err);
						})
					// #endif
					
					
				})
				
			},
			// 計算地圖的高度
			initMapH() {
				// #ifdef APP-PLUS
					this.mapH = uni.getSystemInfoSync().windowHeight - 210;
				// #endif
				// #ifndef APP-PLUS
					this.mapH = uni.getSystemInfoSync().windowHeight - 170;
				// #endif
			},
			// 移動到我的位置
			toMyLocation() {
				this.getLocation()
			},
			// 提交
			submitAdress() {
				this.controls = []
				setTimeout(() => {
					this.$emit('selectAddress', this.addressObj)
				}, 100)
			}
		},
	}
</script>

<style lang="scss" scoped>
	.server-place{
		position: fixed;
		left: 0;
		top: 0;
		height: 100vh;
		width: 100%;
		background: #ffffff;
		z-index: 999;
		.icon-img{
			width: 36px;
			height: 36px;
			display: block;
			position: fixed;
			top: 50%;
			left: 50%;
			transform: translate(-50%, -50%);
			margin-top: -70px;
		}
		.map-tools{
			position: fixed;
			width: 100%;
			bottom: 0rem;
			left: 0;
			padding-bottom: .5rem;
			display: flex;
			justify-content: center;
			align-items: center;
			flex-direction: column;
			.my-location{
				width: 90%;
				margin: 0 auto;
				height: 2.5rem;
				box-shadow: 0px 3px 20px rgba(0, 0, 0, 0.2);
				background: #fff;
				border-radius: 0.5rem;
				display: flex;
				justify-content: flex-start;
				align-items: center;
				overflow: hidden;
				.left{
					background: #3384ff;
					// flex: 20%;
					width: 2.5rem;
					height: 100%;
				}
				.right{
					font-size: 0.57rem;
					margin-left: .5rem;
					color: #111;
					// flex: 80%;
					display: flex;
					justify-content: center;
					align-items: flex-start;
					flex-direction: column;
					.text{
						width: 12rem;
						overflow: hidden;
						white-space:nowrap;
						text-overflow: ellipsis;
						color: #3384FF;
						margin-top: .3rem;
					}
				}
			}
			
			.start-place{
				width: 85%;
				margin: 0 auto;
				height: 5.5rem;
				margin: 0 auto;
				margin-top: .6rem;
				box-shadow: 0px 3px 20px rgba(0, 0, 0, 0.2);
				background: #fff;
				border-radius: 0.5rem;
				padding: .5rem;
				.place{
					.title{
						font-size: 0.67rem;
						font-weight: bold;
						color: #111;
					}
					.text{
						font-size: 0.76rem;
						color: #3384FF;
						font-weight: bold;
						width: 12rem;
						vertical-align: middle;
						display: inline-block;
						margin-left: .5rem;
						overflow: hidden;
						white-space:nowrap;
						text-overflow: ellipsis;
					}
				}
				.tip{
					font-size: 0.57rem;
					color: #666;
					margin-top: .5rem;
				}
				.sure{
					margin-top: .5rem;
					color: #FFFFFF;
					background: #212121;
					font-weight: 600;
				}
				
			}
		}
	}
</style>

4、相關圖標

  https://share.weiyun.com/5aMXvh8

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章