WordPress中Google Map Auto-Complete Search API距离计算异常问题
针对你的两个问题,给出具体排查和修复方案
问题1:距离计算不准确
常见原因及修复方法
使用了错误的距离计算方式
如果你用的是平面几何公式(比如勾股定理)计算距离,会因为地球是球体产生较大误差,尤其是跨区域的地址。必须用Haversine球面距离公式,这是计算地球上两点距离的行业标准。直接替换成下面的PHP实现(适配英里单位):
function calculate_office_distance($user_lat, $user_lon, $office_lat, $office_lon) { // 地球半径(英里) $earth_radius = 3956; // 转弧度计算 $lat_diff = deg2rad($office_lat - $user_lat); $lon_diff = deg2rad($office_lon - $user_lon); $a = sin($lat_diff / 2) * sin($lat_diff / 2) + cos(deg2rad($user_lat)) * cos(deg2rad($office_lat)) * sin($lon_diff / 2) * sin($lon_diff / 2); $c = 2 * atan2(sqrt($a), sqrt(1 - $a)); // 返回英里数,保留1位小数 return round($earth_radius * $c, 1); }坐标或单位转换错误
- 确保你用的是Google API返回的WGS84标准经纬度(Google Maps默认输出这个,不用额外转换)
- 检查单位换算:1英里≈1.609公里,不要把公里数直接当英里用
问题2:连续搜索3-4次后显示超范围办公室
常见原因及修复方法
AJAX请求竞态问题
连续发起无刷新搜索时,旧请求的响应可能晚于新请求,导致旧的超范围结果覆盖新结果。用AbortController取消未完成的旧请求:let searchController; // 绑定搜索表单提交事件 document.querySelector('#office-search-form').addEventListener('submit', (e) => { e.preventDefault(); // 取消之前未完成的请求 if (searchController) searchController.abort(); searchController = new AbortController(); const signal = searchController.signal; // 这里调用Google AutoComplete获取用户地址经纬度,再发起WordPress AJAX请求 fetch(ajaxurl, { method: 'POST', signal: signal, body: new FormData(e.target) }) .then(res => res.json()) .then(data => { // 清空并更新结果容器 document.querySelector('#office-results').innerHTML = data.html; }) .catch(err => { // 忽略主动取消的请求错误 if (err.name !== 'AbortError') console.error(err); }); });结果缓存/全局变量污染
如果你在后台用了全局变量存储办公室列表,或者复用了之前的过滤结果,会导致旧数据残留。每次搜索都要重新从数据库拉取所有办公室数据,重新计算距离并过滤:add_action('wp_ajax_filter_local_offices', 'filter_local_offices'); add_action('wp_ajax_nopriv_filter_local_offices', 'filter_local_offices'); function filter_local_offices() { // 获取用户提交的经纬度 $user_lat = sanitize_text_field($_POST['user_lat']); $user_lon = sanitize_text_field($_POST['user_lon']); // 重新从数据库拉取所有办公室(假设自定义post类型为office) $offices_query = new WP_Query([ 'post_type' => 'office', 'posts_per_page' => -1, 'post_status' => 'publish' ]); $valid_offices = []; if ($offices_query->have_posts()) { while ($offices_query->have_posts()) { $offices_query->the_post(); $office_lat = get_post_meta(get_the_ID(), 'office_lat', true); $office_lon = get_post_meta(get_the_ID(), 'office_lon', true); // 只保留50英里内的办公室 if ($office_lat && $office_lon) { $distance = calculate_office_distance($user_lat, $user_lon, $office_lat, $office_lon); if ($distance <= 50) { $valid_offices[] = [ 'title' => get_the_title(), 'distance' => $distance, 'address' => get_post_meta(get_the_ID(), 'office_address', true) ]; } } } wp_reset_postdata(); } // 生成结果HTML ob_start(); if (!empty($valid_offices)) { foreach ($valid_offices as $office) { echo "<div class='office-item'> <h3>{$office['title']}</h3> <p>{$office['address']}</p> <span>{$office['distance']} 英里</span> </div>"; } } else { echo "<p>未找到50英里范围内的办公室,请扩大搜索范围。</p>"; } $html = ob_get_clean(); wp_send_json(['html' => $html]); wp_die(); }前端结果容器未清空
每次搜索前手动清空结果容器,避免新旧结果叠加:// 在发起AJAX请求前执行 document.querySelector('#office-results').innerHTML = '<div class="loading">加载中...</div>';
内容的提问来源于stack exchange,提问作者Blaze Creative
相关产品推荐
相关产品推荐

