最近在写一个功能,要求实现在h5页面上navigator.geolocation实现定位功能。在移动端测试时,安卓手机都能正常弹出定位提示,提示用户是否开启定位权限。
但是,苹果不可以!!
当时无论怎么测试,苹果都无法打开定位弹窗,在网上找了许久,都没法解决。只能自己搞了。
测试发现,纯粹的HTMl页面是可以让苹果弹出定位开启权限的,但相关代码一旦放入vue文件中就会失灵(到现在我也不知道为什么╮(╯▽╰)╭)。
那没办法喽,只能试试在vue文件中混入HTML文件,并且让他们之间进行相互通讯。
[查阅uniapp文档](web-view | uni-app官网),发现其支持以web-view的形式将html文件混入vue文件中。(我还以为ifame可以,测试发现移动端不行┑( ̄Д  ̄)┍)。
以下是具体实现方法。
HTML部分
uniapp推荐是在根目录下新建一个文件夹放置html文件
下面是内容。文件命名随便起,对的上就行,我这里用的是locate.html。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let pos = ''
// 浏览器定位
function locate() {
navigator.geolocation.getCurrentPosition(success, error, {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0
})
}
function success(position) {
pos = [position.coords.longitude, position.coords.latitude]
}
function error(error) {
switch (error.code) {
case error.PERMISSION_DENIED:
alert('用户拒绝对获取地理位置的请求。')
break;
case error.POSITION_UNAVAILABLE:
alert('位置信息是不可用的。')
break;
case error.TIMEOUT:
alert('请求用户地理位置超时。')
break;
case error.UNKNOWN_ERROR:
alert('未知错误。')
break;
}
}
//获取实时定位需要持续监听
setInterval(() => {
locate()
window.parent.postMessage({
params: JSON.stringify(pos),
}, '*');
}, 2000)
</script>
</body>
</html>
当然,高德的也可以,只是我懒。
Vue部分
vue页面需要引入并监听传来的信息。
引入文件时候注意要将页面大小设置为0,不然web-view会铺满整个页面。
<template>
<view>
<web-view style="width: 0; height: 0;" src="/hybrid/html/locate.html"></web-view>
</view>
</template>
<script setup>
import { onLoad } from '@dcloudio/uni-app'
//创建函数处理监听消息
function handleMessage(event: any) {
let params = JSON.parse(event.data.params);
return params
}
onLoad((e) => {
//创建监听来接受消息
window.addEventListener("message", handleMessage);
})
</script>
这样就可以持续获取苹果的定位。但是这样会导致进入该vue页面就会直接触发。所以可以加上一个判断,当机型是ios时才会触发开启定位。
<template>
<view>
<web-view v-if="isIOS" style="width: 0; height: 0;" src="/hybrid/html/locate.html"></web-view>
</view>
</template>
<script setup>
import { onLoad } from '@dcloudio/uni-app'
//创建函数处理监听消息
function handleMessage(event) {
let params = JSON.parse(event.data.params);
return params
}
const isIOS = ref(false)
function modelJudgment() {
let ran = navigator.userAgent
let ios = !!ran.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/)
let android = ran.indexOf('Android') > -1 || ran.indexOf('Linux') > -1
if (ios) {
isIOS.value = true
window.addEventListener("message", handleMessage);
}
if (android) {
isIOS.value = false
//安卓的定位可以在vue页面实现,这里不过多赘述。
//安卓的定位函数
}
}
onLoad((e) => {
modelJudgment()
})
</script>
这样就可以实现在用uniapp写的h5页面中触发ios的定位弹窗提示了。