地理位置API

地理位置API概述

地理位置API(Geolocation API)是HTML5提供的接口,允许Web应用获取用户的地理位置信息。通过这个API,可以开发基于位置的服务,如地图导航、周边搜索、位置分享等功能。

东巴文(db-w.cn) 认为:地理位置API让Web应用具备了感知位置的能力,为基于位置的服务打开了大门。

地理位置API特点

优点

特点 说明
标准化 W3C标准API,浏览器支持广泛
高精度 支持GPS、WiFi、基站等多种定位方式
隐私保护 需要用户授权才能获取位置
异步获取 不阻塞页面,用户体验好

隐私保护

保护机制 说明
用户授权 首次访问时需要用户明确授权
HTTPS要求 现代浏览器要求HTTPS环境
权限管理 用户可以随时撤销授权
模糊定位 可以提供模糊的位置信息

东巴文点评:隐私保护是地理位置API的重要特性,开发者应该尊重用户隐私,只在必要时请求位置权限。

获取位置

基本用法

// 检查浏览器支持
if ('geolocation' in navigator) {
    console.log('浏览器支持地理位置API');
} else {
    console.log('浏览器不支持地理位置API');
}

// 获取当前位置
navigator.geolocation.getCurrentPosition(
    // 成功回调
    function(position) {
        console.log('纬度:', position.coords.latitude);
        console.log('经度:', position.coords.longitude);
        console.log('精度:', position.coords.accuracy);
    },
    // 错误回调
    function(error) {
        console.error('获取位置失败:', error.message);
    }
);

完整参数

navigator.geolocation.getCurrentPosition(
    successCallback,
    errorCallback,
    options
);

// 成功回调
function successCallback(position) {
    console.log('位置信息:', {
        latitude: position.coords.latitude,        // 纬度
        longitude: position.coords.longitude,      // 经度
        accuracy: position.coords.accuracy,        // 精度(米)
        altitude: position.coords.altitude,        // 海拔(米)
        altitudeAccuracy: position.coords.altitudeAccuracy, // 海拔精度
        heading: position.coords.heading,          // 方向(度)
        speed: position.coords.speed,              // 速度(米/秒)
        timestamp: position.timestamp              // 时间戳
    });
}

// 错误回调
function errorCallback(error) {
    switch (error.code) {
        case error.PERMISSION_DENIED:
            console.error('用户拒绝了位置请求');
            break;
        case error.POSITION_UNAVAILABLE:
            console.error('位置信息不可用');
            break;
        case error.TIMEOUT:
            console.error('请求超时');
            break;
        default:
            console.error('未知错误');
    }
}

// 选项参数
const options = {
    enableHighAccuracy: true,  // 是否使用高精度定位
    timeout: 5000,             // 超时时间(毫秒)
    maximumAge: 0              // 缓存时间(毫秒)
};

navigator.geolocation.getCurrentPosition(
    successCallback,
    errorCallback,
    options
);

选项参数说明

参数 类型 默认值 说明
enableHighAccuracy Boolean false 是否使用高精度定位(如GPS)
timeout Number Infinity 获取位置的超时时间(毫秒)
maximumAge Number 0 缓存位置的最大时间(毫秒)

东巴文点评enableHighAccuracy会消耗更多电量,应该根据实际需求选择是否启用。

持续监听位置

watchPosition方法

// 监听位置变化
const watchId = navigator.geolocation.watchPosition(
    function(position) {
        console.log('位置更新:', position.coords.latitude, position.coords.longitude);
    },
    function(error) {
        console.error('监听失败:', error.message);
    },
    {
        enableHighAccuracy: true,
        timeout: 5000,
        maximumAge: 0
    }
);

// 停止监听
navigator.geolocation.clearWatch(watchId);

实时位置跟踪示例

class LocationTracker {
    constructor() {
        this.watchId = null;
        this.positions = [];
    }
    
    // 开始跟踪
    start(options = {}) {
        const defaultOptions = {
            enableHighAccuracy: true,
            timeout: 10000,
            maximumAge: 0
        };
        
        this.watchId = navigator.geolocation.watchPosition(
            (position) => {
                this.positions.push({
                    latitude: position.coords.latitude,
                    longitude: position.coords.longitude,
                    timestamp: position.timestamp
                });
                
                this.onPositionUpdate(position);
            },
            (error) => {
                this.onError(error);
            },
            { ...defaultOptions, ...options }
        );
        
        return this.watchId;
    }
    
    // 停止跟踪
    stop() {
        if (this.watchId !== null) {
            navigator.geolocation.clearWatch(this.watchId);
            this.watchId = null;
        }
    }
    
    // 获取轨迹
    getTrack() {
        return this.positions;
    }
    
    // 清空轨迹
    clearTrack() {
        this.positions = [];
    }
    
    // 位置更新回调(可重写)
    onPositionUpdate(position) {
        console.log('位置更新:', position);
    }
    
    // 错误回调(可重写)
    onError(error) {
        console.error('位置错误:', error);
    }
}

// 使用示例
const tracker = new LocationTracker();

tracker.onPositionUpdate = function(position) {
    console.log('新位置:', position.coords.latitude, position.coords.longitude);
};

tracker.start();

错误处理

错误类型

错误码 错误名称 说明
1 PERMISSION_DENIED 用户拒绝了位置请求
2 POSITION_UNAVAILABLE 位置信息不可用
3 TIMEOUT 请求超时

错误处理示例

function getLocation() {
    return new Promise((resolve, reject) => {
        if (!('geolocation' in navigator)) {
            reject(new Error('浏览器不支持地理位置API'));
            return;
        }
        
        navigator.geolocation.getCurrentPosition(
            (position) => {
                resolve({
                    latitude: position.coords.latitude,
                    longitude: position.coords.longitude,
                    accuracy: position.coords.accuracy
                });
            },
            (error) => {
                let message = '';
                
                switch (error.code) {
                    case error.PERMISSION_DENIED:
                        message = '用户拒绝了位置请求,请在浏览器设置中允许位置访问';
                        break;
                    case error.POSITION_UNAVAILABLE:
                        message = '无法获取位置信息,请检查设备定位功能是否开启';
                        break;
                    case error.TIMEOUT:
                        message = '获取位置超时,请稍后重试';
                        break;
                    default:
                        message = '获取位置时发生未知错误';
                }
                
                reject(new Error(message));
            },
            {
                enableHighAccuracy: true,
                timeout: 10000,
                maximumAge: 0
            }
        );
    });
}

// 使用
getLocation()
    .then(location => {
        console.log('位置:', location);
    })
    .catch(error => {
        console.error('错误:', error.message);
        // 显示友好的错误提示
        alert(error.message);
    });

东巴文点评:良好的错误处理能提升用户体验,应该为每种错误提供清晰的提示信息。

距离计算

Haversine公式

// 计算两点之间的距离(单位:米)
function calculateDistance(lat1, lon1, lat2, lon2) {
    const R = 6371000; // 地球半径(米)
    
    const φ1 = lat1 * Math.PI / 180;
    const φ2 = lat2 * Math.PI / 180;
    const Δφ = (lat2 - lat1) * Math.PI / 180;
    const Δλ = (lon2 - lon1) * Math.PI / 180;
    
    const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
              Math.cos1) * Math.cos2) *
              Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
    
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    
    return R * c;
}

// 使用示例
const distance = calculateDistance(
    39.9042, 116.4074,  // 北京
    31.2304, 121.4737   // 上海
);

console.log(`距离: ${(distance / 1000).toFixed(2)} 公里`);

距离格式化

function formatDistance(meters) {
    if (meters < 1000) {
        return `${Math.round(meters)} 米`;
    } else if (meters < 10000) {
        return `${(meters / 1000).toFixed(1)} 公里`;
    } else {
        return `${(meters / 1000).toFixed(0)} 公里`;
    }
}

console.log(formatDistance(500));    // 500 米
console.log(formatDistance(1500));   // 1.5 公里
console.log(formatDistance(15000));  // 15 公里

地理编码

逆地理编码(坐标转地址)

地理位置API只提供坐标信息,要获取详细地址需要使用第三方服务(如高德地图、百度地图)。

// 使用高德地图逆地理编码API
async function reverseGeocode(latitude, longitude) {
    const key = 'YOUR_AMAP_KEY'; // 替换为你的高德地图key
    const url = `https://restapi.amap.com/v3/geocode/regeo?key=${key}&location=${longitude},${latitude}`;
    
    try {
        const response = await fetch(url);
        const data = await response.json();
        
        if (data.status === '1') {
            return data.regeocode.formatted_address;
        } else {
            throw new Error('地理编码失败');
        }
    } catch (error) {
        console.error('逆地理编码错误:', error);
        return null;
    }
}

// 使用示例
navigator.geolocation.getCurrentPosition(async (position) => {
    const address = await reverseGeocode(
        position.coords.latitude,
        position.coords.longitude
    );
    
    console.log('当前位置:', address);
});

综合示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>地理位置API示例 - 东巴文</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        
        .section {
            margin: 20px 0;
            padding: 20px;
            border: 1px solid #ddd;
            border-radius: 5px;
        }
        
        button {
            padding: 10px 20px;
            margin: 5px;
            border: none;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
        }
        
        button:hover {
            opacity: 0.9;
        }
        
        button:disabled {
            background: #ccc;
            cursor: not-allowed;
        }
        
        .location-info {
            margin: 15px 0;
            padding: 15px;
            background: #f5f5f5;
            border-radius: 5px;
        }
        
        .location-info p {
            margin: 8px 0;
        }
        
        .location-info strong {
            display: inline-block;
            width: 120px;
        }
        
        .status {
            padding: 10px;
            margin: 10px 0;
            border-radius: 5px;
        }
        
        .status.success {
            background: #d4edda;
            color: #155724;
        }
        
        .status.error {
            background: #f8d7da;
            color: #721c24;
        }
        
        .status.info {
            background: #d1ecf1;
            color: #0c5460;
        }
        
        #map {
            width: 100%;
            height: 300px;
            border: 1px solid #ddd;
            border-radius: 5px;
            margin: 15px 0;
        }
        
        .track-info {
            margin: 10px 0;
            padding: 10px;
            background: #fff3cd;
            border-radius: 5px;
        }
    </style>
</head>
<body>
    <h1>地理位置API示例</h1>
    
    <div class="section">
        <h2>获取当前位置</h2>
        <button onclick="getCurrentLocation()">获取位置</button>
        <div id="currentLocation"></div>
    </div>
    
    <div class="section">
        <h2>实时位置跟踪</h2>
        <button onclick="startTracking()">开始跟踪</button>
        <button onclick="stopTracking()">停止跟踪</button>
        <button onclick="clearTrack()">清空轨迹</button>
        <div id="trackingStatus" class="status info">未开始跟踪</div>
        <div id="trackInfo" class="track-info"></div>
    </div>
    
    <div class="section">
        <h2>距离计算</h2>
        <div class="location-info">
            <p><strong>地点1:</strong> 北京 (39.9042°N, 116.4074°E)</p>
            <p><strong>地点2:</strong> 上海 (31.2304°N, 121.4737°E)</p>
        </div>
        <button onclick="calculateDistance()">计算距离</button>
        <div id="distanceResult"></div>
    </div>
    
    <div class="section">
        <h2>附近地点搜索</h2>
        <p>获取当前位置后,搜索附近的兴趣点</p>
        <button onclick="searchNearby()">搜索附近</button>
        <div id="nearbyResult"></div>
    </div>
    
    <script>
        // 位置跟踪器
        class LocationTracker {
            constructor() {
                this.watchId = null;
                this.positions = [];
            }
            
            start(options = {}) {
                const defaultOptions = {
                    enableHighAccuracy: true,
                    timeout: 10000,
                    maximumAge: 0
                };
                
                this.watchId = navigator.geolocation.watchPosition(
                    (position) => {
                        this.positions.push({
                            latitude: position.coords.latitude,
                            longitude: position.coords.longitude,
                            accuracy: position.coords.accuracy,
                            timestamp: position.timestamp
                        });
                        
                        this.onPositionUpdate(position);
                    },
                    (error) => {
                        this.onError(error);
                    },
                    { ...defaultOptions, ...options }
                );
                
                return this.watchId;
            }
            
            stop() {
                if (this.watchId !== null) {
                    navigator.geolocation.clearWatch(this.watchId);
                    this.watchId = null;
                }
            }
            
            getTrack() {
                return this.positions;
            }
            
            clearTrack() {
                this.positions = [];
            }
            
            onPositionUpdate(position) {
                console.log('位置更新:', position);
            }
            
            onError(error) {
                console.error('位置错误:', error);
            }
        }
        
        const tracker = new LocationTracker();
        let currentPosition = null;
        
        // 获取当前位置
        function getCurrentLocation() {
            const container = document.getElementById('currentLocation');
            container.innerHTML = '<div class="status info">获取位置中...</div>';
            
            if (!('geolocation' in navigator)) {
                container.innerHTML = '<div class="status error">浏览器不支持地理位置API</div>';
                return;
            }
            
            navigator.geolocation.getCurrentPosition(
                (position) => {
                    currentPosition = position;
                    
                    const coords = position.coords;
                    container.innerHTML = `
                        <div class="status success">位置获取成功</div>
                        <div class="location-info">
                            <p><strong>纬度:</strong> ${coords.latitude.toFixed(6)}°</p>
                            <p><strong>经度:</strong> ${coords.longitude.toFixed(6)}°</p>
                            <p><strong>精度:</strong> ${coords.accuracy.toFixed(2)} 米</p>
                            ${coords.altitude ? `<p><strong>海拔:</strong> ${coords.altitude.toFixed(2)} 米</p>` : ''}
                            ${coords.speed ? `<p><strong>速度:</strong> ${coords.speed.toFixed(2)} 米/秒</p>` : ''}
                            <p><strong>时间:</strong> ${new Date(position.timestamp).toLocaleString()}</p>
                        </div>
                    `;
                },
                (error) => {
                    let message = '';
                    
                    switch (error.code) {
                        case error.PERMISSION_DENIED:
                            message = '用户拒绝了位置请求';
                            break;
                        case error.POSITION_UNAVAILABLE:
                            message = '位置信息不可用';
                            break;
                        case error.TIMEOUT:
                            message = '请求超时';
                            break;
                        default:
                            message = '未知错误';
                    }
                    
                    container.innerHTML = `<div class="status error">错误: ${message}</div>`;
                },
                {
                    enableHighAccuracy: true,
                    timeout: 10000,
                    maximumAge: 0
                }
            );
        }
        
        // 开始跟踪
        function startTracking() {
            const statusEl = document.getElementById('trackingStatus');
            const trackInfoEl = document.getElementById('trackInfo');
            
            tracker.onPositionUpdate = function(position) {
                const coords = position.coords;
                const track = tracker.getTrack();
                
                statusEl.className = 'status success';
                statusEl.textContent = '跟踪中...';
                
                trackInfoEl.innerHTML = `
                    <p><strong>当前纬度:</strong> ${coords.latitude.toFixed(6)}°</p>
                    <p><strong>当前经度:</strong> ${coords.longitude.toFixed(6)}°</p>
                    <p><strong>轨迹点数:</strong> ${track.length}</p>
                    <p><strong>精度:</strong> ${coords.accuracy.toFixed(2)} 米</p>
                `;
            };
            
            tracker.onError = function(error) {
                statusEl.className = 'status error';
                statusEl.textContent = '跟踪错误: ' + error.message;
            };
            
            tracker.start();
        }
        
        // 停止跟踪
        function stopTracking() {
            tracker.stop();
            
            const statusEl = document.getElementById('trackingStatus');
            statusEl.className = 'status info';
            statusEl.textContent = '已停止跟踪';
        }
        
        // 清空轨迹
        function clearTrack() {
            tracker.clearTrack();
            document.getElementById('trackInfo').innerHTML = '';
        }
        
        // 计算距离
        function calculateDistance() {
            const resultEl = document.getElementById('distanceResult');
            
            // 北京坐标
            const beijing = { lat: 39.9042, lon: 116.4074 };
            // 上海坐标
            const shanghai = { lat: 31.2304, lon: 121.4737 };
            
            const distance = haversineDistance(beijing.lat, beijing.lon, shanghai.lat, shanghai.lon);
            
            resultEl.innerHTML = `
                <div class="status success">
                    北京到上海的距离: ${formatDistance(distance)}
                </div>
            `;
        }
        
        // Haversine公式计算距离
        function haversineDistance(lat1, lon1, lat2, lon2) {
            const R = 6371000; // 地球半径(米)
            
            const φ1 = lat1 * Math.PI / 180;
            const φ2 = lat2 * Math.PI / 180;
            const Δφ = (lat2 - lat1) * Math.PI / 180;
            const Δλ = (lon2 - lon1) * Math.PI / 180;
            
            const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
                      Math.cos1) * Math.cos2) *
                      Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
            
            const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            
            return R * c;
        }
        
        // 格式化距离
        function formatDistance(meters) {
            if (meters < 1000) {
                return `${Math.round(meters)} 米`;
            } else if (meters < 10000) {
                return `${(meters / 1000).toFixed(1)} 公里`;
            } else {
                return `${(meters / 1000).toFixed(0)} 公里`;
            }
        }
        
        // 搜索附近
        function searchNearby() {
            const resultEl = document.getElementById('nearbyResult');
            
            if (!currentPosition) {
                resultEl.innerHTML = '<div class="status error">请先获取当前位置</div>';
                return;
            }
            
            // 模拟附近地点数据
            const nearbyPlaces = [
                { name: '咖啡厅', distance: 150, type: '餐饮' },
                { name: '公园', distance: 300, type: '休闲' },
                { name: '超市', distance: 500, type: '购物' },
                { name: '医院', distance: 800, type: '医疗' },
                { name: '学校', distance: 1000, type: '教育' }
            ];
            
            resultEl.innerHTML = `
                <div class="status success">找到 ${nearbyPlaces.length} 个附近地点</div>
                <div class="location-info">
                    ${nearbyPlaces.map(place => `
                        <p><strong>${place.name}</strong> - ${place.type} - ${formatDistance(place.distance)}</p>
                    `).join('')}
                </div>
            `;
        }
        
        // 页面卸载时停止跟踪
        window.addEventListener('beforeunload', function() {
            tracker.stop();
        });
    </script>
</body>
</html>

最佳实践

1. 检查浏览器支持

// 推荐:先检查支持性
if ('geolocation' in navigator) {
    navigator.geolocation.getCurrentPosition(success, error);
} else {
    // 提供降级方案
    alert('您的浏览器不支持地理位置功能');
}

// 不推荐:直接调用
navigator.geolocation.getCurrentPosition(success, error);

2. 错误处理

// 推荐:完善的错误处理
navigator.geolocation.getCurrentPosition(
    (position) => {
        // 成功处理
        updateLocation(position);
    },
    (error) => {
        // 根据错误类型提供友好提示
        switch (error.code) {
            case error.PERMISSION_DENIED:
                showTip('请在浏览器设置中允许位置访问');
                break;
            case error.POSITION_UNAVAILABLE:
                showTip('无法获取位置,请检查定位服务是否开启');
                break;
            case error.TIMEOUT:
                showTip('获取位置超时,请稍后重试');
                break;
        }
    }
);

3. 合理使用选项

// 推荐:根据场景选择选项
// 高精度场景(如导航)
navigator.geolocation.getCurrentPosition(success, error, {
    enableHighAccuracy: true,
    timeout: 10000,
    maximumAge: 0
});

// 低精度场景(如天气查询)
navigator.geolocation.getCurrentPosition(success, error, {
    enableHighAccuracy: false,
    timeout: 5000,
    maximumAge: 300000 // 5分钟缓存
});

东巴文点评:高精度定位会消耗更多电量,应该根据实际需求选择合适的定位精度。

4. 及时清理监听

// 推荐:及时清理watchPosition
let watchId = null;

function startWatch() {
    watchId = navigator.geolocation.watchPosition(callback);
}

function stopWatch() {
    if (watchId !== null) {
        navigator.geolocation.clearWatch(watchId);
        watchId = null;
    }
}

// 页面卸载时清理
window.addEventListener('beforeunload', stopWatch);

// 不推荐:不清理watchPosition
navigator.geolocation.watchPosition(callback);
// 忘记清理,导致持续消耗资源

学习检验

知识点测试

问题1:地理位置API获取位置时,用户拒绝授权的错误码是?

A. 0 B. 1 C. 2 D. 3

<details> <summary>点击查看答案</summary>

答案:B

东巴文解释:错误码1表示PERMISSION_DENIED,即用户拒绝了位置请求。

</details>

问题2:以下哪个选项用于设置获取位置的超时时间?

A. timeout B. maximumAge C. enableHighAccuracy D. delay

<details> <summary>点击查看答案</summary>

答案:A

东巴文解释timeout选项用于设置获取位置的超时时间(毫秒),maximumAge是缓存时间,enableHighAccuracy是高精度开关。

</details>

实践任务

任务:创建一个位置分享应用,获取用户当前位置并显示坐标,可以复制位置信息分享给他人。

<details> <summary>点击查看参考答案</summary>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>位置分享</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 50px auto;
            padding: 20px;
        }
        
        .location-card {
            padding: 20px;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            border-radius: 10px;
            margin: 20px 0;
        }
        
        .location-card h2 {
            margin-top: 0;
        }
        
        .coords {
            font-size: 24px;
            font-weight: bold;
            margin: 15px 0;
        }
        
        .coords small {
            font-size: 14px;
            opacity: 0.8;
        }
        
        button {
            padding: 12px 24px;
            margin: 5px;
            border: none;
            background: white;
            color: #667eea;
            border-radius: 5px;
            cursor: pointer;
            font-size: 16px;
        }
        
        button:hover {
            opacity: 0.9;
        }
        
        .share-link {
            margin: 20px 0;
            padding: 15px;
            background: #f5f5f5;
            border-radius: 5px;
            word-break: break-all;
        }
        
        .tip {
            padding: 10px;
            background: #fff3cd;
            border-radius: 5px;
            margin: 10px 0;
        }
    </style>
</head>
<body>
    <h1>位置分享</h1>
    
    <button onclick="getLocation()">获取我的位置</button>
    
    <div id="locationCard" class="location-card" style="display: none;">
        <h2>我的位置</h2>
        <div class="coords">
            <div id="latDisplay"></div>
            <div id="lonDisplay"></div>
        </div>
        <p id="timeDisplay"></p>
        <button onclick="copyLocation()">复制位置信息</button>
        <button onclick="shareLocation()">生成分享链接</button>
    </div>
    
    <div id="shareLink" class="share-link" style="display: none;"></div>
    
    <div id="tip" class="tip" style="display: none;"></div>
    
    <script>
        let currentLocation = null;
        
        function getLocation() {
            if (!('geolocation' in navigator)) {
                showTip('您的浏览器不支持地理位置功能', 'error');
                return;
            }
            
            showTip('获取位置中...', 'info');
            
            navigator.geolocation.getCurrentPosition(
                (position) => {
                    currentLocation = {
                        latitude: position.coords.latitude,
                        longitude: position.coords.longitude,
                        accuracy: position.coords.accuracy,
                        timestamp: position.timestamp
                    };
                    
                    displayLocation(currentLocation);
                    showTip('位置获取成功', 'success');
                },
                (error) => {
                    let message = '';
                    
                    switch (error.code) {
                        case error.PERMISSION_DENIED:
                            message = '您拒绝了位置请求';
                            break;
                        case error.POSITION_UNAVAILABLE:
                            message = '位置信息不可用';
                            break;
                        case error.TIMEOUT:
                            message = '获取位置超时';
                            break;
                        default:
                            message = '获取位置失败';
                    }
                    
                    showTip(message, 'error');
                },
                {
                    enableHighAccuracy: true,
                    timeout: 10000,
                    maximumAge: 0
                }
            );
        }
        
        function displayLocation(location) {
            document.getElementById('locationCard').style.display = 'block';
            
            document.getElementById('latDisplay').innerHTML = `
                ${location.latitude.toFixed(6)}° <small>纬度</small>
            `;
            
            document.getElementById('lonDisplay').innerHTML = `
                ${location.longitude.toFixed(6)}° <small>经度</small>
            `;
            
            document.getElementById('timeDisplay').textContent = `
                获取时间: ${new Date(location.timestamp).toLocaleString()}
            `;
        }
        
        function copyLocation() {
            if (!currentLocation) {
                showTip('请先获取位置', 'error');
                return;
            }
            
            const text = `我的位置: ${currentLocation.latitude.toFixed(6)}°N, ${currentLocation.longitude.toFixed(6)}°E`;
            
            navigator.clipboard.writeText(text).then(() => {
                showTip('位置信息已复制到剪贴板', 'success');
            }).catch(() => {
                showTip('复制失败,请手动复制', 'error');
            });
        }
        
        function shareLocation() {
            if (!currentLocation) {
                showTip('请先获取位置', 'error');
                return;
            }
            
            const url = `${window.location.origin}${window.location.pathname}?lat=${currentLocation.latitude}&lon=${currentLocation.longitude}`;
            
            const shareLinkEl = document.getElementById('shareLink');
            shareLinkEl.style.display = 'block';
            shareLinkEl.innerHTML = `
                <strong>分享链接:</strong><br>
                <a href="${url}" target="_blank">${url}</a>
            `;
            
            showTip('分享链接已生成', 'success');
        }
        
        function showTip(message, type) {
            const tipEl = document.getElementById('tip');
            tipEl.style.display = 'block';
            tipEl.textContent = message;
            tipEl.style.background = type === 'success' ? '#d4edda' : 
                                     type === 'error' ? '#f8d7da' : '#fff3cd';
        }
        
        // 检查URL参数
        const params = new URLSearchParams(window.location.search);
        const lat = params.get('lat');
        const lon = params.get('lon');
        
        if (lat && lon) {
            currentLocation = {
                latitude: parseFloat(lat),
                longitude: parseFloat(lon),
                timestamp: Date.now()
            };
            
            displayLocation(currentLocation);
            showTip('这是分享的位置', 'info');
        }
    </script>
</body>
</html>
</details>

东巴文(db-w.cn) - 让编程学习更有趣、更高效!