我有一个很简单的JS使用navigator。geolocation。getcurrentposition jammy。
$(document).ready(function(){
$("#business-locate, #people-locate").click(function() {
navigator.geolocation.getCurrentPosition(foundLocation, noLocation);
});
navigator.geolocation.getCurrentPosition(foundLocation, noLocation);
function foundLocation(position) {
var lat = position.coords.latitude;
var lon = position.coords.longitude;
var userLocation = lat + ', ' + lon;
$("#business-current-location, #people-current-location").remove();
$("#Near-Me")
.watermark("Current Location")
.after("<input type='hidden' name='business-current-location' id='business-current-location' value='"+userLocation+"' />");
$("#people-Near-Me")
.watermark("Current Location")
.after("<input type='hidden' name='people-current-location' id='people-current-location' value='"+userLocation+"' />");
}
function noLocation() {
$("#Near-Me").watermark("Could not find location");
$("#people-Near-Me").watermark("Could not find location");
}
})//end DocReady
基本上,这里发生的事情是我们得到当前位置,如果它得到了,两个“水印”被放置在两个字段中,表示“当前位置”,两个隐藏字段被创建,并使用latong数据作为它们的值(它们在开始时被删除,这样它们就不会每次都重复)。还有两个按钮,它们有一个点击功能,做同样的事情。
不幸的是,每隔三次左右,它就会奏效。
这里有什么问题?
传递给geolocation . getcurrentposition()的第二个参数是要处理任何地理位置错误的函数。错误处理函数本身接收一个PositionError对象,其中包含关于地理定位尝试失败原因的详细信息。我建议输出错误到控制台,如果你有任何问题:
var positionOptions = { timeout: 10000 };
navigator.geolocation.getCurrentPosition(updateLocation, errorHandler, positionOptions);
function updateLocation(position) {
// The geolocation succeeded, and the position is available
}
function errorHandler(positionError) {
if (window.console) {
console.log(positionError);
}
}
Doing this in my code revealed the message "Network location provider at 'https://www.googleapis.com/' : Returned error code 400". Turns out Google Chrome uses the Google APIs to get a location on devices that don't have GPS built in (for example, most desktop computers). Google returns an approximate latitude/longitude based on the user's IP address. However, in developer builds of Chrome (such as Chromium on Ubuntu) there is no API access key included in the browser build. This causes the API request to fail silently. See Chromium Issue 179686: Geolocation giving 403 error for details.
截至2020年年中,这里的答案都没有提供任何解释,只是黑客攻击或猜测。
正如@Coderer在我之前指出的,安全上下文(https)是今天需要的,所以在越来越多的设备上,地理定位在普通http下根本不起作用:
安全上下文
此特性仅在安全上下文中(HTTPS)以及部分或所有支持的浏览器中可用。
getCurrentPosition()(和watchPosition()更适合这里)的第三个参数是PositionOptions对象,由以下属性组成:
enableHighAccurancy (default false): if set to true, response is slower and more accurate. If you got timeout errors, keep this to false. If the accurancy is low, set it to true. In my tests the accurancy varies and on some devices it has no effect. On other devices setting true may cause surprisingly quick battery depletion.
timeout (default infinity): milliseconds before the API gives up and calls the error handler (the second parameter). Today most mobile devices with geolocation enabled and permission granted for the browser/page get the value with reasonable accurancy within a second. When the geolocation service is not available, alternative method like geo IP may be used, the delay can be many seconds and the precision usually ranges from questionable to useless.
maximumAge (default 0): milliseconds when cached value is valid, the device may decide to use valid cached data instead of sensor measure. I usually set this to non-zero values with slowly moving devices (like walking with mobile phone). On static devices, Infinity can be set to avoid consequent reading errors.
正如@YoLoCo在我之前指出的那样,getCurrentPosition()和watchPosition()会干扰,我在2020年确认了他的结果。通常,使用watchPosition代替getCurrentPosition周期性调用。
这是我解决这个问题的hack方法,至少它在所有当前的浏览器中都有效(在Windows上,我没有Mac):
if (navigator.geolocation) {
var location_timeout = setTimeout("geolocFail()", 10000);
navigator.geolocation.getCurrentPosition(function(position) {
clearTimeout(location_timeout);
var lat = position.coords.latitude;
var lng = position.coords.longitude;
geocodeLatLng(lat, lng);
}, function(error) {
clearTimeout(location_timeout);
geolocFail();
});
} else {
// Fallback for no geolocation
geolocFail();
}
如果有人点击“关闭”或选择“不”或在Firefox上选择“永不共享”选项,这也会起作用。
很笨拙,但很有效。
我终于找到了一个工作版本的firefox, chrome和默认导航器在android(仅4.2测试):
function getGeoLocation() {
var options = null;
if (navigator.geolocation) {
if (browserChrome) //set this var looking for Chrome un user-agent header
options={enableHighAccuracy: false, maximumAge: 15000, timeout: 30000};
else
options={maximumAge:Infinity, timeout:0};
navigator.geolocation.getCurrentPosition(getGeoLocationCallback,
getGeoLocationErrorCallback,
options);
}
}
在我们的例子中,它总是第一次工作,但重新运行函数3-4次以上,它就失败了。
简单的解决方法:将其值存储在LocalStorage中。
之前:
navigator.geolocation.getCurrentPosition((position) => {
let val = results[0].address_components[2].long_name;
doSthWithVal(val);
}, (error) => { });
后:
if(localStorage.getItem('getCurrentPosition') !== null) {
doSthWithVal(localStorage.getItem('getCurrentPosition'));
}
else {
navigator.geolocation.getCurrentPosition((position) => {
let val = results[0].address_components[2].long_name;
localStorage.setItem('getCurrentPosition',val);
doSthWithVal(val);
}, (error) => { });
}