如何在手机到达指定区域时设置Oracle APEX项目值?
问题解决:儿童竞速PWA的圈数计数失效问题
核心问题分析
- 定位精度与跳变特性:民用GPS定位本身存在3-5米的误差,且位置更新不是连续平滑的,直接用
==判断当前经度与起点经度完全匹配,几乎不可能触发。 - 起点线模型错误:10米长的水平线并非绝对同一经度(地球是球面,短距离内经度差极小,但更合理的是将起点定义为地理区域,而非单一坐标值)。
- 数据类型错误:把经纬度存在DOM元素的
innerHTML中会转为字符串,数值比较时容易出现精度丢失或类型不匹配问题。 - 无状态控制:如果停留在起点区域内,会重复触发圈数累加,导致计数错误。
解决方案代码
HTML部分
<label for="round_no">圈数:</label> <input id="round_no" value="0"> <br><br> <label for="starting_area_info">起点区域范围:</label> <input id="starting_area_info" readonly> <br><br> <label for="current_location">当前位置:</label> <input id="current_location" readonly>
JavaScript部分
// 存储起点区域边界和状态,避免重复计数 let startArea = { minLat: 0, maxLat: 0, minLng: 0, maxLng: 0, isInArea: false }; // 初始化起点区域:基于初始位置计算10米范围的地理边界 navigator.geolocation.getCurrentPosition(function(position) { const coords = position.coords; // 10米对应的经纬度偏移近似值(纬度1度≈111km,经度1度≈111km*cos(纬度)) const meterToLat = 10 / 111000; const meterToLng = 10 / (111000 * Math.cos(coords.latitude * Math.PI / 180)); // 定义起点矩形区域,覆盖10米长的水平线范围 startArea.minLat = coords.latitude - meterToLat / 2; startArea.maxLat = coords.latitude + meterToLat / 2; startArea.minLng = coords.longitude - meterToLng / 2; startArea.maxLng = coords.longitude + meterToLng / 2; // 显示起点区域信息 document.getElementById("starting_area_info").value = `纬度: ${startArea.minLat.toFixed(6)} ~ ${startArea.maxLat.toFixed(6)}, 经度: ${startArea.minLng.toFixed(6)} ~ ${startArea.maxLng.toFixed(6)}`; updateCurrentLocation(coords); }, function(error) { alert(`定位初始化失败: ${error.message}`); }, { enableHighAccuracy: true, // 启用高精度定位 timeout: 5000, maximumAge: 0 }); // 监听位置变化,判断是否进入起点区域 navigator.geolocation.watchPosition(function(position) { const coords = position.coords; updateCurrentLocation(coords); // 判断当前是否在起点区域内 const currentInArea = coords.latitude >= startArea.minLat && coords.latitude <= startArea.maxLat && coords.longitude >= startArea.minLng && coords.longitude <= startArea.maxLng; // 仅当从区域外进入区域内时,累加圈数 if (currentInArea && !startArea.isInArea) { const roundInput = document.getElementById("round_no"); roundInput.value = Number(roundInput.value) + 1; startArea.isInArea = true; } else if (!currentInArea) { startArea.isInArea = false; // 离开区域时重置状态 } }, function(error) { console.error(`定位更新失败: ${error.message}`); }, { enableHighAccuracy: true, timeout: 5000, maximumAge: 0, frequency: 1000 // 每秒更新一次位置 }); // 辅助函数:更新当前位置显示 function updateCurrentLocation(coords) { document.getElementById("current_location").value = `纬度: ${coords.latitude.toFixed(6)}, 经度: ${coords.longitude.toFixed(6)}`; }
关键优化点
- 区域判断替代全等匹配:将起点定义为矩形地理区域,只要当前位置落在区域内即判定为回到起点。
- 状态控制:通过
isInArea标记避免在起点区域内重复累加圈数,仅触发一次进入动作。 - 高精度定位配置:开启
enableHighAccuracy参数,提升定位精度。 - 数值化存储:直接用变量存储经纬度数值,避免DOM字符串转换带来的精度问题。
- 错误处理:添加定位失败提示,增强应用稳定性。
内容的提问来源于stack exchange,提问作者Eslam
相关产品推荐
相关产品推荐

