地理位置手表不会持续触发
Posted
技术标签:
【中文标题】地理位置手表不会持续触发【英文标题】:Geolocation watch doesn't fire consistently 【发布时间】:2015-08-01 17:19:38 【问题描述】:我有一个测试应用程序,它从 html5 地理定位服务获取 lat/lng 值。不幸的是,它以相当不一致的时间间隔发射,从 500 毫秒到 10000 毫秒不等。我已经尝试更改手表的 maximimAge 和 timeout 参数,但这些似乎并没有改变任何东西。我正在 Chrome 中以及通过 android Lollipop 构建上的简单 Cordova 应用程序对其进行测试。下面的代码仅显示手表的时间戳值,以消除可能导致问题的任何其他延迟。似乎该间隔接近 1 秒然后 5 秒的重复模式。我还尝试将地理位置获取函数放在 setInterval 函数中,它的行为具有相同的 1 秒和 5 秒重复间隔。
<html>
<body>
<h1>Timestamp</h1>
<div id="mytimestamp"></div>
<button id="btnstopwatch">Stop GPS</button>
</body>
</html>
<script type="text/javascript">
var mytimestamp = document.getElementById("mytimestamp");
//start watching location
watchPositionId = navigator.geolocation.watchPosition(updateCompass,handleerror,
enableHighAccuracy:true,
maximumAge:3000,
timeout:3000
);
function updateCompass(p)
mytimestamp.innerHTML = p.timestamp;
function handleerror(err)
if(err.code ==1)
//user said no
alert('Please allow access to GPS');
else
alert(err.code);
</script>
【问题讨论】:
【参考方案1】:关于 watchPosition(),在下面的 link w3 中说“只有在获得新位置时才调用successCallback ......实现可能会对频率施加限制回调,以避免无意中消耗不成比例的资源。”
这意味着 watchPosition() 正在等待会导致位置发生变化的事件,否则它什么也不做。所以 watchPosition() 不会调用 updateCompass() 除非它看到位置的变化。 另外,关于watchPosition(),maximumAge和timeout参数与获取新位置有关,这些参数与watchPosition()的次数和时间无关被称为...
WatchPosition() 防止连续调用以查看位置是否发生变化,并且仅在发生与位置变化相关的某些事件时才做出反应,这有助于节省电池等资源。但是如果你真的想看位置,比如说每三秒一次,不管位置是否改变,我认为设置一个间隔是个好方法。
var watchPositionId;
//start watching location
setInterval(function ()
watchPositionId = navigator.geolocation.watchPosition(updateCompass, handleerror,
enableHighAccuracy: true,
maximumAge: 3000,
timeout: 3000
);
, 3000);
function updateCompass(p)
mytimestamp.innerHTML = p.timestamp;
// if you have alert message it will counts seconds once you dismiss the alert,
//this may be part of the issue why you kept getting diffrent intervals.
//alert(p.timestamp);
navigator.geolocation.clearWatch(watchPositionId);
您提到您尝试 setInterval 但它不起作用,所以请注意我在上面的代码中注释了 alert() 因为它导致我有延迟,没有它,html 中的时间戳每 3000 毫秒更新一次精度约5ms。
如果您想使用 watchPosition(),上述方法有效,因为 clearWatch() 会停止 watchPosition() 并进一步回调。基本上,上面的代码每三秒启动一次新的 watchPosition() 并用 clearWatch() 终止它。话虽如此,我认为 watchPosition() 不是在这种方法中使用的最佳方法,除非您预计在此时间间隔内位置会发生重大变化。我宁愿使用 getCurrentPosition() ,因为它可以完成工作并且不等待位置变化。
var watchPositionId;
//start watching location
setInterval(function ()
watchPositionId = navigator.geolocation.getCurrentPosition(updateCompass, handleerror,
enableHighAccuracy: true,
maximumAge: 3000,
timeout: 3000
);
, 3000);
function updateCompass(p)
mytimestamp.innerHTML = p.timestamp;
【讨论】:
我将代码更改为使用 getCurrentPosition 函数,现在它会在 4.5 到 6.5 秒之间更新。我很快将把它加入到 Cordova 应用程序中,看看它是否会继续以这种方式运行。目前,我可以忍受这种不一致,希望它在编译成本机代码后会变得更加一致。 请记住,如果您的代码中有 alert(),则在您单击警报上的“确定”按钮后,时间间隔的时间就会开始计算,因此您的时间戳将具有比预期更长的时间。 【参考方案2】:我最终将解决方案更改为同时使用地理位置和 deviceOrientationEvent。单独使用地理定位事件会产生非常“生涩”的响应,而设备方向事件可以消除这种情况。
这里的 setInterval 函数设置为每十秒获取一次地理位置:
window.onload = function()
//fetch new GPS info every 10000 milliseconds
window.setInterval(function ()
navigator.geolocation.getCurrentPosition(onGeoSuccess, onGeoFailure,
enableHighAccuracy: true,
maximumAge: 0,
timeout: 30000 //large timeout to accomodate slow GPS lock on some devices
);
, 10000); //update current location every ten seconds
;
关于地理上的成功:
function onGeoSuccess(location)
//call function to calculate bearing
var cluebearing = geo.bearing(currentlat, currentlng, cluelat, cluelng);
//call function to rotate arrow
rotateArrow(cluebearing);
//end onGeoSuccess()
获取设备方向和进程的功能:
function rotateArrow(mybearing)
//Check for support for DeviceOrientation event
if(window.DeviceOrientationEvent)
//orientation listener
window.addEventListener('deviceorientation', function(event)
var myalpha = event.alpha; //rotation from north
//process orientation change
//end deviceorientation listener
//end rotateArrow()
关于地理故障:
function onGeoFailure()
alert('Please turn on your phone\'s GPS');
【讨论】:
以上是关于地理位置手表不会持续触发的主要内容,如果未能解决你的问题,请参考以下文章
Android地理围栏不会触发一次位置关闭和再次打开[重复]