Skip to content

9.2 地理定位API

关键词

地理定位、Geolocation API、GPS定位、位置服务、坐标获取、位置监听、HTML5 API

学习目标

  • 理解HTML5地理定位API的概念和作用
  • 掌握地理定位的基本用法和属性
  • 学会在HTML中声明和使用地理定位相关元素
  • 理解地理定位的隐私和安全考虑
  • 能够创建支持地理定位的HTML应用结构

详细内容

9.2.1 地理定位API概述

什么是地理定位

HTML5地理定位API允许网页获取用户的地理位置信息:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML5地理定位API</title>
    <meta name="description" content="学习HTML5地理定位API的基本概念和应用">
</head>
<body>
    <header>
        <h1>HTML5地理定位API</h1>
        <nav>
            <ul>
                <li><a href="#basic">基础用法</a></li>
                <li><a href="#applications">应用场景</a></li>
                <li><a href="#privacy">隐私考虑</a></li>
            </ul>
        </nav>
    </header>
    
    <main>
        <section id="introduction">
            <h2>地理定位简介</h2>
            <article>
                <h3>定位方式对比</h3>
                <table>
                    <thead>
                        <tr>
                            <th>定位方式</th>
                            <th>精度</th>
                            <th>速度</th>
                            <th>耗电量</th>
                            <th>可用性</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>GPS</td>
                            <td>高(1-5米)</td>
                            <td>慢</td>
                            <td>高</td>
                            <td>户外</td>
                        </tr>
                        <tr>
                            <td>Wi-Fi</td>
                            <td>中(10-100米)</td>
                            <td>快</td>
                            <td>中</td>
                            <td>有Wi-Fi的地方</td>
                        </tr>
                        <tr>
                            <td>基站</td>
                            <td>低(100-2000米)</td>
                            <td>快</td>
                            <td>低</td>
                            <td>有信号的地方</td>
                        </tr>
                        <tr>
                            <td>IP地址</td>
                            <td>很低(城市级别)</td>
                            <td>很快</td>
                            <td>很低</td>
                            <td>任何地方</td>
                        </tr>
                    </tbody>
                </table>
            </article>
        </section>
        
        <section id="basic">
            <h2>基础地理定位</h2>
            <article>
                <h3>位置获取界面</h3>
                <div class="location-demo">
                    <h4>获取当前位置</h4>
                    <div class="location-panel">
                        <div class="location-request">
                            <h5>位置请求</h5>
                            <p>点击按钮获取您的当前位置:</p>
                            <button type="button" onclick="getCurrentLocation()" 
                                    data-action="getCurrentLocation">
                                获取位置
                            </button>
                            <button type="button" onclick="clearLocation()" 
                                    data-action="clearLocation">
                                清除位置
                            </button>
                        </div>
                        
                        <div class="location-display">
                            <h5>位置信息</h5>
                            <dl>
                                <dt>纬度:</dt>
                                <dd id="latitude" data-location="latitude">未获取</dd>
                                
                                <dt>经度:</dt>
                                <dd id="longitude" data-location="longitude">未获取</dd>
                                
                                <dt>精度:</dt>
                                <dd id="accuracy" data-location="accuracy">未获取</dd>
                                
                                <dt>海拔:</dt>
                                <dd id="altitude" data-location="altitude">未获取</dd>
                                
                                <dt>海拔精度:</dt>
                                <dd id="altitudeAccuracy" data-location="altitudeAccuracy">未获取</dd>
                                
                                <dt>方向:</dt>
                                <dd id="heading" data-location="heading">未获取</dd>
                                
                                <dt>速度:</dt>
                                <dd id="speed" data-location="speed">未获取</dd>
                                
                                <dt>时间戳:</dt>
                                <dd id="timestamp" data-location="timestamp">未获取</dd>
                            </dl>
                        </div>
                        
                        <div class="location-options">
                            <h5>定位选项</h5>
                            <fieldset>
                                <legend>定位参数</legend>
                                
                                <label for="enable-high-accuracy">
                                    <input type="checkbox" id="enable-high-accuracy" 
                                           data-option="enableHighAccuracy">
                                    启用高精度定位
                                </label>
                                
                                <label for="timeout">
                                    超时时间:
                                    <input type="range" id="timeout" name="timeout" 
                                           min="1000" max="30000" value="10000" step="1000"
                                           data-option="timeout">
                                    <span id="timeout-value">10秒</span>
                                </label>
                                
                                <label for="maximum-age">
                                    缓存时间:
                                    <input type="range" id="maximum-age" name="maximumAge" 
                                           min="0" max="300000" value="60000" step="10000"
                                           data-option="maximumAge">
                                    <span id="maximum-age-value">60秒</span>
                                </label>
                            </fieldset>
                        </div>
                    </div>
                </div>
            </article>
        </section>
        
        <section id="applications">
            <h2>实际应用场景</h2>
            
            <article>
                <h3>本地服务查找</h3>
                <div class="location-demo">
                    <h4>附近服务</h4>
                    <div class="service-finder">
                        <div class="service-search">
                            <h5>搜索附近服务</h5>
                            <form id="service-search-form">
                                <label for="service-type">服务类型:</label>
                                <select id="service-type" name="serviceType" 
                                        data-search="serviceType">
                                    <option value="">请选择服务类型</option>
                                    <option value="restaurant">餐厅</option>
                                    <option value="hospital">医院</option>
                                    <option value="school">学校</option>
                                    <option value="bank">银行</option>
                                    <option value="gas-station">加油站</option>
                                    <option value="pharmacy">药店</option>
                                </select>
                                
                                <label for="search-radius">搜索半径:</label>
                                <input type="range" id="search-radius" name="radius" 
                                       min="500" max="10000" value="2000" step="500"
                                       data-search="radius">
                                <span id="radius-value">2公里</span>
                                
                                <button type="button" onclick="searchNearbyServices()"
                                        data-action="searchNearbyServices">
                                    搜索附近服务
                                </button>
                            </form>
                        </div>
                        
                        <div class="service-results">
                            <h5>搜索结果</h5>
                            <div id="service-list" data-results="nearbyServices">
                                <!-- 搜索结果将在这里显示 -->
                            </div>
                        </div>
                    </div>
                </div>
            </article>
            
            <article>
                <h3>位置签到</h3>
                <div class="location-demo">
                    <h4>签到系统</h4>
                    <div class="checkin-system">
                        <div class="checkin-form">
                            <h5>位置签到</h5>
                            <form id="checkin-form">
                                <div class="form-group">
                                    <label for="checkin-place">签到地点:</label>
                                    <input type="text" id="checkin-place" name="place" 
                                           placeholder="请输入地点名称" 
                                           data-checkin="place">
                                </div>
                                
                                <div class="form-group">
                                    <label for="checkin-note">签到备注:</label>
                                    <textarea id="checkin-note" name="note" rows="3" 
                                              placeholder="请输入签到备注" 
                                              data-checkin="note"></textarea>
                                </div>
                                
                                <div class="form-group">
                                    <label for="checkin-photo">上传照片:</label>
                                    <input type="file" id="checkin-photo" name="photo" 
                                           accept="image/*" 
                                           data-checkin="photo">
                                </div>
                                
                                <div class="form-group">
                                    <label>
                                        <input type="checkbox" id="share-location" 
                                               name="shareLocation" 
                                               data-checkin="shareLocation">
                                        公开分享位置
                                    </label>
                                </div>
                                
                                <button type="button" onclick="checkInAtLocation()"
                                        data-action="checkInAtLocation">
                                    签到
                                </button>
                            </form>
                        </div>
                        
                        <div class="checkin-history">
                            <h5>签到历史</h5>
                            <div id="checkin-list" data-history="checkins">
                                <!-- 签到历史将在这里显示 -->
                            </div>
                            
                            <div class="history-actions">
                                <button type="button" onclick="loadCheckinHistory()"
                                        data-action="loadCheckinHistory">
                                    刷新历史
                                </button>
                                <button type="button" onclick="clearCheckinHistory()"
                                        data-action="clearCheckinHistory">
                                    清除历史
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </article>
            
            <article>
                <h3>路线规划</h3>
                <div class="location-demo">
                    <h4>导航系统</h4>
                    <div class="navigation-system">
                        <div class="route-planner">
                            <h5>路线规划</h5>
                            <form id="route-form">
                                <div class="form-group">
                                    <label for="start-location">起始位置:</label>
                                    <input type="text" id="start-location" name="startLocation" 
                                           placeholder="请输入起始位置" 
                                           data-route="startLocation">
                                    <button type="button" onclick="useCurrentLocationAsStart()"
                                            data-action="useCurrentLocationAsStart">
                                        使用当前位置
                                    </button>
                                </div>
                                
                                <div class="form-group">
                                    <label for="end-location">目的地:</label>
                                    <input type="text" id="end-location" name="endLocation" 
                                           placeholder="请输入目的地" 
                                           data-route="endLocation">
                                </div>
                                
                                <div class="form-group">
                                    <label for="travel-mode">出行方式:</label>
                                    <select id="travel-mode" name="travelMode" 
                                            data-route="travelMode">
                                        <option value="driving">驾车</option>
                                        <option value="walking">步行</option>
                                        <option value="cycling">骑行</option>
                                        <option value="transit">公共交通</option>
                                    </select>
                                </div>
                                
                                <div class="form-group">
                                    <label for="avoid-options">避开选项:</label>
                                    <fieldset>
                                        <label>
                                            <input type="checkbox" name="avoid" value="tolls" 
                                                   data-route="avoidTolls">
                                            收费站
                                        </label>
                                        <label>
                                            <input type="checkbox" name="avoid" value="highways" 
                                                   data-route="avoidHighways">
                                            高速公路
                                        </label>
                                        <label>
                                            <input type="checkbox" name="avoid" value="ferries" 
                                                   data-route="avoidFerries">
                                            轮渡
                                        </label>
                                    </fieldset>
                                </div>
                                
                                <button type="button" onclick="planRoute()"
                                        data-action="planRoute">
                                    规划路线
                                </button>
                            </form>
                        </div>
                        
                        <div class="route-results">
                            <h5>路线信息</h5>
                            <div id="route-info" data-results="routeInfo">
                                <!-- 路线信息将在这里显示 -->
                            </div>
                        </div>
                        
                        <div class="route-map">
                            <h5>路线地图</h5>
                            <div id="map-container" data-map="routeMap">
                                <!-- 地图将在这里显示 -->
                                <p>地图占位符 - 实际应用中可以集成第三方地图服务</p>
                            </div>
                        </div>
                    </div>
                </div>
            </article>
        </section>
        
        <section id="advanced">
            <h2>高级地理定位应用</h2>
            
            <article>
                <h3>位置监听</h3>
                <div class="location-demo">
                    <h4>实时位置跟踪</h4>
                    <div class="tracking-system">
                        <div class="tracking-controls">
                            <h5>跟踪控制</h5>
                            <button type="button" onclick="startLocationTracking()"
                                    data-action="startLocationTracking">
                                开始跟踪
                            </button>
                            <button type="button" onclick="stopLocationTracking()"
                                    data-action="stopLocationTracking">
                                停止跟踪
                            </button>
                            <button type="button" onclick="clearTrackingData()"
                                    data-action="clearTrackingData">
                                清除数据
                            </button>
                        </div>
                        
                        <div class="tracking-status">
                            <h5>跟踪状态</h5>
                            <dl>
                                <dt>状态:</dt>
                                <dd id="tracking-status" data-tracking="status">未开始</dd>
                                
                                <dt>更新次数:</dt>
                                <dd id="update-count" data-tracking="updateCount">0</dd>
                                
                                <dt>总距离:</dt>
                                <dd id="total-distance" data-tracking="totalDistance">0米</dd>
                                
                                <dt>平均速度:</dt>
                                <dd id="average-speed" data-tracking="averageSpeed">0 km/h</dd>
                                
                                <dt>跟踪时间:</dt>
                                <dd id="tracking-time" data-tracking="trackingTime">00:00:00</dd>
                            </dl>
                        </div>
                        
                        <div class="tracking-path">
                            <h5>轨迹记录</h5>
                            <div id="path-list" data-tracking="pathList">
                                <!-- 轨迹点将在这里显示 -->
                            </div>
                        </div>
                    </div>
                </div>
            </article>
            
            <article>
                <h3>地理围栏</h3>
                <div class="location-demo">
                    <h4>区域监控</h4>
                    <div class="geofence-system">
                        <div class="geofence-setup">
                            <h5>围栏设置</h5>
                            <form id="geofence-form">
                                <div class="form-group">
                                    <label for="fence-name">围栏名称:</label>
                                    <input type="text" id="fence-name" name="name" 
                                           placeholder="请输入围栏名称" 
                                           data-geofence="name">
                                </div>
                                
                                <div class="form-group">
                                    <label for="fence-center-lat">中心纬度:</label>
                                    <input type="number" id="fence-center-lat" name="centerLat" 
                                           step="0.000001" placeholder="请输入中心纬度" 
                                           data-geofence="centerLat">
                                </div>
                                
                                <div class="form-group">
                                    <label for="fence-center-lng">中心经度:</label>
                                    <input type="number" id="fence-center-lng" name="centerLng" 
                                           step="0.000001" placeholder="请输入中心经度" 
                                           data-geofence="centerLng">
                                </div>
                                
                                <div class="form-group">
                                    <label for="fence-radius">半径(米):</label>
                                    <input type="range" id="fence-radius" name="radius" 
                                           min="50" max="5000" value="500" step="50"
                                           data-geofence="radius">
                                    <span id="fence-radius-value">500米</span>
                                </div>
                                
                                <div class="form-group">
                                    <label for="fence-action">触发动作:</label>
                                    <select id="fence-action" name="action" 
                                            data-geofence="action">
                                        <option value="enter">进入时触发</option>
                                        <option value="exit">离开时触发</option>
                                        <option value="both">进入和离开都触发</option>
                                    </select>
                                </div>
                                
                                <button type="button" onclick="createGeofence()"
                                        data-action="createGeofence">
                                    创建围栏
                                </button>
                            </form>
                        </div>
                        
                        <div class="geofence-list">
                            <h5>围栏列表</h5>
                            <div id="fence-list" data-geofence="fenceList">
                                <!-- 围栏列表将在这里显示 -->
                            </div>
                        </div>
                        
                        <div class="geofence-alerts">
                            <h5>围栏警报</h5>
                            <div id="alert-list" data-geofence="alertList">
                                <!-- 警报记录将在这里显示 -->
                            </div>
                        </div>
                    </div>
                </div>
            </article>
        </section>
        
        <section id="privacy">
            <h2>隐私和安全考虑</h2>
            
            <article>
                <h3>用户授权</h3>
                <div class="privacy-demo">
                    <h4>权限管理</h4>
                    <div class="permission-system">
                        <div class="permission-request">
                            <h5>权限请求</h5>
                            <p>使用地理定位功能需要用户明确授权:</p>
                            <div class="permission-info">
                                <ul>
                                    <li>浏览器会显示权限请求对话框</li>
                                    <li>用户可以选择允许或拒绝</li>
                                    <li>权限状态会被记住</li>
                                    <li>用户可以随时修改权限设置</li>
                                </ul>
                            </div>
                        </div>
                        
                        <div class="permission-status">
                            <h5>权限状态</h5>
                            <div id="permission-status" data-permission="status">
                                <p>当前权限状态:<span id="current-permission">未检查</span></p>
                                <button type="button" onclick="checkPermissionStatus()"
                                        data-action="checkPermissionStatus">
                                    检查权限状态
                                </button>
                            </div>
                        </div>
                    </div>
                </div>
            </article>
            
            <article>
                <h3>数据保护</h3>
                <div class="privacy-demo">
                    <h4>隐私保护措施</h4>
                    <div class="privacy-measures">
                        <div class="privacy-guidelines">
                            <h5>隐私指导原则</h5>
                            <ul>
                                <li><strong>最小化原则</strong>:只获取必要的位置信息</li>
                                <li><strong>透明度原则</strong>:明确告知用户数据用途</li>
                                <li><strong>控制权原则</strong>:用户可以随时撤销权限</li>
                                <li><strong>安全存储</strong>:位置数据需要安全存储</li>
                                <li><strong>有限使用</strong>:仅用于声明的目的</li>
                            </ul>
                        </div>
                        
                        <div class="privacy-settings">
                            <h5>隐私设置</h5>
                            <form id="privacy-form">
                                <fieldset>
                                    <legend>数据使用设置</legend>
                                    
                                    <label>
                                        <input type="checkbox" name="allowDataCollection" 
                                               data-privacy="allowDataCollection">
                                        允许收集位置数据
                                    </label>
                                    
                                    <label>
                                        <input type="checkbox" name="allowDataSharing" 
                                               data-privacy="allowDataSharing">
                                        允许共享位置数据
                                    </label>
                                    
                                    <label>
                                        <input type="checkbox" name="allowDataAnalysis" 
                                               data-privacy="allowDataAnalysis">
                                        允许分析位置数据
                                    </label>
                                    
                                    <label>
                                        <input type="checkbox" name="allowLocationHistory" 
                                               data-privacy="allowLocationHistory">
                                        允许保存位置历史
                                    </label>
                                </fieldset>
                                
                                <div class="privacy-actions">
                                    <button type="button" onclick="savePrivacySettings()"
                                            data-action="savePrivacySettings">
                                        保存设置
                                    </button>
                                    <button type="button" onclick="deleteLocationData()"
                                            data-action="deleteLocationData">
                                        删除位置数据
                                    </button>
                                </div>
                            </form>
                        </div>
                    </div>
                </div>
            </article>
        </section>
    </main>
    
    <aside>
        <h2>地理定位API特性</h2>
        <dl>
            <dt>支持情况</dt>
            <dd>现代浏览器都支持,移动设备支持更好</dd>
            
            <dt>精度范围</dt>
            <dd>取决于设备和定位方式,1米到数公里不等</dd>
            
            <dt>权限要求</dt>
            <dd>需要用户明确授权才能使用</dd>
            
            <dt>HTTPS要求</dt>
            <dd>在生产环境中必须使用HTTPS</dd>
            
            <dt>隐私考虑</dt>
            <dd>涉及用户隐私,需要谨慎处理</dd>
        </dl>
    </aside>
    
    <footer>
        <p>&copy; 2024 HTML5地理定位API学习文档</p>
        <p><small>注意:本示例仅展示HTML结构,实际定位功能需要JavaScript实现</small></p>
    </footer>
    
    <!-- 模拟的JavaScript功能说明 -->
    <script type="text/plain">
        // 注意:这里只是展示HTML结构,实际的JavaScript功能需要单独实现
        
        // 基础定位功能
        function getCurrentLocation() {
            // 获取当前位置
        }
        
        function clearLocation() {
            // 清除位置信息
        }
        
        // 服务搜索功能
        function searchNearbyServices() {
            // 搜索附近服务
        }
        
        // 签到功能
        function checkInAtLocation() {
            // 在当前位置签到
        }
        
        function loadCheckinHistory() {
            // 加载签到历史
        }
        
        // 导航功能
        function planRoute() {
            // 规划路线
        }
        
        function useCurrentLocationAsStart() {
            // 使用当前位置作为起点
        }
        
        // 位置跟踪功能
        function startLocationTracking() {
            // 开始位置跟踪
        }
        
        function stopLocationTracking() {
            // 停止位置跟踪
        }
        
        // 地理围栏功能
        function createGeofence() {
            // 创建地理围栏
        }
        
        // 权限管理功能
        function checkPermissionStatus() {
            // 检查权限状态
        }
        
        function savePrivacySettings() {
            // 保存隐私设置
        }
        
        function deleteLocationData() {
            // 删除位置数据
        }
    </script>
</body>
</html>

9.2.2 位置获取详解

基本位置信息

详细解析位置对象的各个属性:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>位置对象详解</title>
</head>
<body>
    <header>
        <h1>位置对象属性详解</h1>
        <p>理解地理定位返回的位置信息</p>
    </header>
    
    <main>
        <section class="position-details">
            <h2>Position对象结构</h2>
            <article>
                <h3>坐标信息(coords)</h3>
                <div class="coords-display">
                    <table>
                        <thead>
                            <tr>
                                <th>属性</th>
                                <th>类型</th>
                                <th>描述</th>
                                <th>当前值</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>latitude</td>
                                <td>number</td>
                                <td>纬度(-90到90)</td>
                                <td id="coord-latitude" data-coord="latitude">-</td>
                            </tr>
                            <tr>
                                <td>longitude</td>
                                <td>number</td>
                                <td>经度(-180到180)</td>
                                <td id="coord-longitude" data-coord="longitude">-</td>
                            </tr>
                            <tr>
                                <td>accuracy</td>
                                <td>number</td>
                                <td>水平精度(米)</td>
                                <td id="coord-accuracy" data-coord="accuracy">-</td>
                            </tr>
                            <tr>
                                <td>altitude</td>
                                <td>number|null</td>
                                <td>海拔高度(米)</td>
                                <td id="coord-altitude" data-coord="altitude">-</td>
                            </tr>
                            <tr>
                                <td>altitudeAccuracy</td>
                                <td>number|null</td>
                                <td>海拔精度(米)</td>
                                <td id="coord-altitude-accuracy" data-coord="altitudeAccuracy">-</td>
                            </tr>
                            <tr>
                                <td>heading</td>
                                <td>number|null</td>
                                <td>方向(0-360度)</td>
                                <td id="coord-heading" data-coord="heading">-</td>
                            </tr>
                            <tr>
                                <td>speed</td>
                                <td>number|null</td>
                                <td>速度(米/秒)</td>
                                <td id="coord-speed" data-coord="speed">-</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
                
                <div class="position-actions">
                    <button type="button" onclick="getDetailedPosition()"
                            data-action="getDetailedPosition">
                        获取详细位置
                    </button>
                    <button type="button" onclick="refreshPosition()"
                            data-action="refreshPosition">
                        刷新位置
                    </button>
                </div>
            </article>
            
            <article>
                <h3>时间信息(timestamp)</h3>
                <div class="timestamp-display">
                    <dl>
                        <dt>获取时间:</dt>
                        <dd id="position-timestamp" data-timestamp="position">未获取</dd>
                        
                        <dt>本地时间:</dt>
                        <dd id="local-time" data-timestamp="local">未获取</dd>
                        
                        <dt>UTC时间:</dt>
                        <dd id="utc-time" data-timestamp="utc">未获取</dd>
                        
                        <dt>时区偏移:</dt>
                        <dd id="timezone-offset" data-timestamp="timezone">未获取</dd>
                    </dl>
                </div>
            </article>
        </section>
        
        <section class="position-options">
            <h2>定位选项配置</h2>
            <article>
                <h3>PositionOptions对象</h3>
                <div class="options-config">
                    <form id="position-options-form">
                        <fieldset>
                            <legend>定位参数设置</legend>
                            
                            <div class="option-group">
                                <h4>enableHighAccuracy</h4>
                                <label>
                                    <input type="checkbox" id="high-accuracy" name="enableHighAccuracy" 
                                           data-option="enableHighAccuracy">
                                    启用高精度定位
                                </label>
                                <p class="option-description">
                                    启用后会使用GPS等高精度定位方式,但耗电量增加,定位时间延长
                                </p>
                            </div>
                            
                            <div class="option-group">
                                <h4>timeout</h4>
                                <label for="timeout-setting">
                                    超时时间:
                                    <input type="range" id="timeout-setting" name="timeout" 
                                           min="1000" max="60000" value="15000" step="1000"
                                           data-option="timeout">
                                    <span id="timeout-display">15秒</span>
                                </label>
                                <p class="option-description">
                                    定位请求的最大等待时间,超时后会返回错误
                                </p>
                            </div>
                            
                            <div class="option-group">
                                <h4>maximumAge</h4>
                                <label for="max-age-setting">
                                    缓存时间:
                                    <input type="range" id="max-age-setting" name="maximumAge" 
                                           min="0" max="600000" value="300000" step="30000"
                                           data-option="maximumAge">
                                    <span id="max-age-display">5分钟</span>
                                </label>
                                <p class="option-description">
                                    接受缓存位置的最大时间,设为0表示总是获取新位置
                                </p>
                            </div>
                        </fieldset>
                        
                        <div class="options-actions">
                            <button type="button" onclick="testPositionOptions()"
                                    data-action="testPositionOptions">
                                测试设置
                            </button>
                            <button type="button" onclick="resetPositionOptions()"
                                    data-action="resetPositionOptions">
                                重置设置
                            </button>
                        </div>
                    </form>
                </div>
            </article>
        </section>
        
        <section class="error-handling">
            <h2>错误处理</h2>
            <article>
                <h3>PositionError对象</h3>
                <div class="error-display">
                    <table>
                        <thead>
                            <tr>
                                <th>错误代码</th>
                                <th>错误常量</th>
                                <th>描述</th>
                                <th>可能原因</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td>1</td>
                                <td>PERMISSION_DENIED</td>
                                <td>权限被拒绝</td>
                                <td>用户拒绝了定位请求</td>
                            </tr>
                            <tr>
                                <td>2</td>
                                <td>POSITION_UNAVAILABLE</td>
                                <td>位置不可用</td>
                                <td>设备无法确定位置</td>
                            </tr>
                            <tr>
                                <td>3</td>
                                <td>TIMEOUT</td>
                                <td>请求超时</td>
                                <td>在指定时间内未获取到位置</td>
                            </tr>
                        </tbody>
                    </table>
                </div>
                
                <div class="error-simulation">
                    <h4>错误模拟</h4>
                    <div class="error-controls">
                        <button type="button" onclick="simulatePermissionError()"
                                data-action="simulatePermissionError">
                            模拟权限错误
                        </button>
                        <button type="button" onclick="simulateTimeoutError()"
                                data-action="simulateTimeoutError">
                            模拟超时错误
                        </button>
                        <button type="button" onclick="simulateUnavailableError()"
                                data-action="simulateUnavailableError">
                            模拟不可用错误
                        </button>
                    </div>
                    
                    <div class="error-message">
                        <h5>错误信息</h5>
                        <div id="error-display" data-error="message">
                            暂无错误
                        </div>
                    </div>
                </div>
            </article>
        </section>
    </main>
    
    <aside>
        <h2>定位精度说明</h2>
        <div class="accuracy-info">
            <h3>精度等级</h3>
            <ul>
                <li><strong>GPS</strong>:1-5米(户外,晴天)</li>
                <li><strong>A-GPS</strong>:3-5米(辅助GPS)</li>
                <li><strong>Wi-Fi</strong>:10-100米(室内)</li>
                <li><strong>基站</strong>:100-2000米(移动网络)</li>
                <li><strong>IP地址</strong>:1000-50000米(网络定位)</li>
            </ul>
        </div>
    </aside>
    
    <footer>
        <p><small>注意:定位精度受多种因素影响,实际精度可能有所差异</small></p>
    </footer>
</body>
</html>

9.2.3 实时位置监听

持续位置跟踪

实现实时位置监听和轨迹记录:

html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>实时位置监听</title>
</head>
<body>
    <header>
        <h1>实时位置监听</h1>
        <p>持续跟踪用户位置变化</p>
    </header>
    
    <main>
        <section class="watch-position">
            <h2>位置监听控制</h2>
            <article>
                <h3>监听管理</h3>
                <div class="watch-controls">
                    <div class="control-panel">
                        <h4>控制面板</h4>
                        <div class="control-buttons">
                            <button type="button" onclick="startWatchingPosition()"
                                    data-action="startWatchingPosition">
                                开始监听
                            </button>
                            <button type="button" onclick="stopWatchingPosition()"
                                    data-action="stopWatchingPosition">
                                停止监听
                            </button>
                            <button type="button" onclick="pauseWatchingPosition()"
                                    data-action="pauseWatchingPosition">
                                暂停监听
                            </button>
                            <button type="button" onclick="resumeWatchingPosition()"
                                    data-action="resumeWatchingPosition">
                                恢复监听
                            </button>
                        </div>
                    </div>
                    
                    <div class="watch-status">
                        <h4>监听状态</h4>
                        <dl>
                            <dt>状态:</dt>
                            <dd id="watch-status" data-watch="status">未开始</dd>
                            
                            <dt>监听ID:</dt>
                            <dd id="watch-id" data-watch="id">-</dd>
                            
                            <dt>更新次数:</dt>
                            <dd id="update-count" data-watch="updateCount">0</dd>
                            
                            <dt>开始时间:</dt>
                            <dd id="start-time" data-watch="startTime">-</dd>
                            
                            <dt>持续时间:</dt>
                            <dd id="duration" data-watch="duration">00:00:00</dd>
                            
                            <dt>上次更新:</dt>
                            <dd id="last-update" data-watch="lastUpdate">-</dd>
                        </dl>
                    </div>
                </div>
            </article>
            
            <article>
                <h3>监听配置</h3>
                <div class="watch-config">
                    <form id="watch-config-form">
                        <fieldset>
                            <legend>监听参数</legend>
                            
                            <div class="config-group">
                                <label for="watch-high-accuracy">
                                    <input type="checkbox" id="watch-high-accuracy" 
                                           name="enableHighAccuracy" 
                                           data-config="enableHighAccuracy">
                                    启用高精度定位
                                </label>
                            </div>
                            
                            <div class="config-group">
                                <label for="watch-timeout">
                                    超时时间:
                                    <input type="range" id="watch-timeout" name="timeout" 
                                           min="5000" max="60000" value="15000" step="5000"
                                           data-config="timeout">
                                    <span id="watch-timeout-display">15秒</span>
                                </label>
                            </div>
                            
                            <div class="config-group">
                                <label for="watch-maximum-age">
                                    缓存时间:
                                    <input type="range" id="watch-maximum-age" name="maximumAge" 
                                           min="0" max="300000" value="60000" step="10000"
                                           data-config="maximumAge">
                                    <span id="watch-maximum-age-display">60秒</span>
                                </label>
                            </div>
                            
                            <div class="config-group">
                                <label for="update-interval">
                                    更新间隔:
                                    <input type="range" id="update-interval" name="interval" 
                                           min="1000" max="60000" value="10000" step="1000"
                                           data-config="interval">
                                    <span id="update-interval-display">10秒</span>
                                </label>
                            </div>
                        </fieldset>
                        
                        <div class="config-actions">
                            <button type="button" onclick="saveWatchConfig()"
                                    data-action="saveWatchConfig">
                                保存配置
                            </button>
                            <button type="button" onclick="resetWatchConfig()"
                                    data-action="resetWatchConfig">
                                重置配置
                            </button>
                        </div>
                    </form>
                </div>
            </article>
        </section>
        
        <section class="position-tracking">
            <h2>位置跟踪记录</h2>
            <article>
                <h3>实时位置信息</h3>
                <div class="current-position">
                    <h4>当前位置</h4>
                    <div class="position-info">
                        <table>
                            <thead>
                                <tr>
                                    <th>属性</th>
                                    <th>数值</th>
                                    <th>变化</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td>纬度</td>
                                    <td id="current-lat" data-current="latitude">-</td>
                                    <td id="lat-change" data-change="latitude">-</td>
                                </tr>
                                <tr>
                                    <td>经度</td>
                                    <td id="current-lng" data-current="longitude">-</td>
                                    <td id="lng-change" data-change="longitude">-</td>
                                </tr>
                                <tr>
                                    <td>精度</td>
                                    <td id="current-accuracy" data-current="accuracy">-</td>
                                    <td id="accuracy-change" data-change="accuracy">-</td>
                                </tr>
                                <tr>
                                    <td>速度</td>
                                    <td id="current-speed" data-current="speed">-</td>
                                    <td id="speed-change" data-change="speed">-</td>
                                </tr>
                                <tr>
                                    <td>方向</td>
                                    <td id="current-heading" data-current="heading">-</td>
                                    <td id="heading-change" data-change="heading">-</td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </article>
            
            <article>
                <h3>轨迹统计</h3>
                <div class="tracking-stats">
                    <h4>移动统计</h4>
                    <div class="stats-grid">
                        <div class="stat-item">
                            <h5>总距离</h5>
                            <p id="total-distance" data-stat="totalDistance">0米</p>
                        </div>
                        
                        <div class="stat-item">
                            <h5>平均速度</h5>
                            <p id="avg-speed" data-stat="avgSpeed">0 km/h</p>
                        </div>
                        
                        <div class="stat-item">
                            <h5>最高速度</h5>
                            <p id="max-speed" data-stat="maxSpeed">0 km/h</p>
                        </div>
                        
                        <div class="stat-item">
                            <h5>移动时间</h5>
                            <p id="moving-time" data-stat="movingTime">00:00:00</p>
                        </div>
                        
                        <div class="stat-item">
                            <h5>停留时间</h5>
                            <p id="stationary-time" data-stat="stationaryTime">00:00:00</p>
                        </div>
                        
                        <div class="stat-item">
                            <h5>位置点数</h5>
                            <p id="point-count" data-stat="pointCount">0</p>
                        </div>
                    </div>
                </div>
            </article>
            
            <article>
                <h3>轨迹记录</h3>
                <div class="track-log">
                    <h4>位置历史</h4>
                    <div class="log-controls">
                        <button type="button" onclick="exportTrackLog()"
                                data-action="exportTrackLog">
                            导出轨迹
                        </button>
                        <button type="button" onclick="clearTrackLog()"
                                data-action="clearTrackLog">
                            清除记录
                        </button>
                        <button type="button" onclick="showTrackOnMap()"
                                data-action="showTrackOnMap">
                            显示地图
                        </button>
                    </div>
                    
                    <div class="log-table">
                        <table id="track-log-table">
                            <thead>
                                <tr>
                                    <th>时间</th>
                                    <th>纬度</th>
                                    <th>经度</th>
                                    <th>精度</th>
                                    <th>速度</th>
                                    <th>距离</th>
                                </tr>
                            </thead>
                            <tbody id="track-log-body" data-log="trackLog">
                                <!-- 轨迹记录将在这里显示 -->
                            </tbody>
                        </table>
                    </div>
                </div>
            </article>
        </section>
        
        <section class="advanced-features">
            <h2>高级功能</h2>
            
            <article>
                <h3>运动检测</h3>
                <div class="motion-detection">
                    <h4>运动状态</h4>
                    <div class="motion-status">
                        <div class="status-indicator">
                            <h5>当前状态</h5>
                            <p id="motion-state" data-motion="state">未知</p>
                        </div>
                        
                        <div class="motion-settings">
                            <h5>检测设置</h5>
                            <form id="motion-settings-form">
                                <label for="motion-threshold">
                                    运动阈值:
                                    <input type="range" id="motion-threshold" name="threshold" 
                                           min="0.1" max="5.0" value="1.0" step="0.1"
                                           data-motion="threshold">
                                    <span id="motion-threshold-display">1.0 m/s</span>
                                </label>
                                
                                <label for="stationary-timeout">
                                    静止超时:
                                    <input type="range" id="stationary-timeout" name="timeout" 
                                           min="30" max="300" value="60" step="30"
                                           data-motion="timeout">
                                    <span id="stationary-timeout-display">60秒</span>
                                </label>
                            </form>
                        </div>
                    </div>
                </div>
            </article>
            
            <article>
                <h3>位置预测</h3>
                <div class="position-prediction">
                    <h4>位置预测</h4>
                    <div class="prediction-info">
                        <div class="predicted-position">
                            <h5>预测位置</h5>
                            <dl>
                                <dt>预测时间:</dt>
                                <dd id="prediction-time" data-prediction="time">-</dd>
                                
                                <dt>预测纬度:</dt>
                                <dd id="predicted-lat" data-prediction="latitude">-</dd>
                                
                                <dt>预测经度:</dt>
                                <dd id="predicted-lng" data-prediction="longitude">-</dd>
                                
                                <dt>预测精度:</dt>
                                <dd id="prediction-accuracy" data-prediction="accuracy">-</dd>
                            </dl>
                        </div>
                        
                        <div class="prediction-settings">
                            <h5>预测设置</h5>
                            <form id="prediction-settings-form">
                                <label for="prediction-duration">
                                    预测时长:
                                    <input type="range" id="prediction-duration" name="duration" 
                                           min="10" max="300" value="60" step="10"
                                           data-prediction="duration">
                                    <span id="prediction-duration-display">60秒</span>
                                </label>
                                
                                <button type="button" onclick="calculatePrediction()"
                                        data-action="calculatePrediction">
                                    计算预测
                                </button>
                            </form>
                        </div>
                    </div>
                </div>
            </article>
        </section>
    </main>
    
    <aside>
        <h2>watchPosition特性</h2>
        <dl>
            <dt>持续监听</dt>
            <dd>会持续监听位置变化,直到主动停止</dd>
            
            <dt>返回值</dt>
            <dd>返回监听ID,用于停止监听</dd>
            
            <dt>回调频率</dt>
            <dd>根据位置变化和设备性能自动调整</dd>
            
            <dt>电池消耗</dt>
            <dd>持续定位会消耗更多电池</dd>
            
            <dt>权限保持</dt>
            <dd>需要用户授权且保持权限状态</dd>
        </dl>
    </aside>
    
    <footer>
        <p><small>注意:长时间使用位置监听会消耗设备电量</small></p>
    </footer>
</body>
</html>

关键要点总结

  1. 基础定位:使用getCurrentPosition()获取一次性位置信息
  2. 持续监听:使用watchPosition()实现实时位置跟踪
  3. 权限管理:需要用户明确授权,遵循隐私原则
  4. 错误处理:正确处理各种定位错误情况
  5. 精度配置:根据需求配置定位精度和超时时间

参考资源

常见问题解答

Q: 地理定位在哪些情况下不可用? A: 用户拒绝权限、设备不支持、网络连接问题、GPS信号弱等情况。

Q: 如何提高定位精度? A: 启用高精度模式、在开阔地带使用、结合多种定位方式。

Q: 地理定位API是否需要网络连接? A: GPS不需要网络,但Wi-Fi和基站定位需要网络连接。

Q: 如何处理定位权限被拒绝的情况? A: 提供友好的错误提示,引导用户手动开启权限。

Q: watchPosition()如何优化电池使用? A: 合理设置更新间隔,不需要时及时停止监听。