首先说明以下代码适合有前端基础知识的同学。
以下是css和html部分
<!DOCTYPE html>
<html lang="zh-CN">
<!-- lang是用来申明语言类型,这里申明为中文(zh)中国大陆(CN)
补充中文繁体为zh-TW -->
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>腾讯地图逆地址解析</title>
<script src="https://map.qq.com/api/gljs?v=1.exp&key=你的key&libraries=service"></script>
<!--接口地址的引入,加 &libraries=service,为了避免location格式错误 -->
<style>
:root {
/* 在根元素的伪类中自定义了一些颜色,方便后续引用 */
/* 放在:root中,是因为它是全局属性 */
--primary: #1a2980;
--secondary: #26d0ce;
--light: #f8f9ff;
--dark: #0f1a5c;
--success: #2ecc71;
--danger: #e74c3c;
--warning: #f39c12;
}
* {
box-sizing: border-box;
/* 防止盒子被撑大 */
margin: 0;
padding: 0;
/* 清除默认格式 */
font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
}
body {
background: linear-gradient(135deg, var(--primary), var(--secondary));
/* 渐变背景 */
color: #333;
min-height: 100vh;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
}
.container {
width: 100%;
max-width: 1000px;
background: rgba(255, 255, 255, 0.95);
border-radius: 16px;
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.25);
overflow: hidden;
display: flex;
flex-direction: column;
}
header {
background: var(--primary);
/* 自定义引用变量 */
background: linear-gradient(90deg, var(--primary), var(--secondary));
color: white;
padding: 25px;
text-align: center;
position: relative;
overflow: hidden;
}
header::before {
content: "";
position: absolute;
top: -50px;
left: -50px;
width: 150px;
height: 150px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
}
header::after {
content: "";
position: absolute;
bottom: -30px;
right: -30px;
width: 100px;
height: 100px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.1);
}
h1 {
font-size: 32px;
margin-bottom: 10px;
position: relative;
z-index: 2;
}
.subtitle {
font-size: 17px;
opacity: 0.9;
position: relative;
z-index: 2;
}
.content {
display: flex;
flex-wrap: wrap;
/* flex-wrap: nowrap | wrap | wrap-reverse;
当一行排不下时,允许换行 */
padding: 20px;
}
.input-section {
flex: 1;
min-width: 300px;
padding: 20px;
}
.map-section {
flex: 1;
min-width: 300px;
height: 400px;
border-radius: 10px;
overflow: hidden;
background: #f0f0f0;
position: relative;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}
#map {
width: 100%;
height: 100%;
}
.input-group {
margin-bottom: 25px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: var(--primary);
font-size: 16px;
}
input {
width: 100%;
padding: 14px 18px;
border: 2px solid #dde4ff;
border-radius: 10px;
font-size: 17px;
transition: all 0.3s;
background: #f8f9ff;
}
input:focus {
border-color: var(--primary);
outline: none;
box-shadow: 0 0 0 3px rgba(26, 41, 128, 0.2);
}
.button-group {
display: flex;
gap: 15px;
margin-top: 30px;
}
button {
flex: 1;
padding: 15px;
border: none;
border-radius: 10px;
font-size: 17px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
button i {
font-size: 20px;
}
#parseBtn {
background: var(--primary);
color: white;
}
#getLocationBtn {
background: var(--secondary);
color: white;
}
button:hover {
transform: translateY(-3px);
box-shadow: 0 6px 15px rgba(0, 0, 0, 0.15);
}
#parseBtn:hover {
background: var(--dark);
}
#getLocationBtn:hover {
background: #1db9b7;
}
.result-section {
padding: 25px;
background: var(--light);
border-radius: 12px;
margin-top: 25px;
border: 1px solid #e0e7ff;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.05);
}
.result-title {
font-size: 22px;
color: var(--primary);
margin-bottom: 20px;
padding-bottom: 12px;
border-bottom: 3px solid var(--primary);
display: flex;
align-items: center;
gap: 10px;
}
.result-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 20px;
}
.result-item {
background: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.06);
border-left: 4px solid var(--primary);
transition: transform 0.3s;
}
.result-item:hover {
transform: translateY(-5px);
}
.result-label {
font-size: 15px;
color: #666;
margin-bottom: 8px;
display: flex;
align-items: center;
gap: 6px;
}
.result-value {
font-size: 19px;
font-weight: 700;
color: var(--primary);
word-break: break-all;
/* 用于控制文本换行规则的属性,可将单词拆开,避免溢出 */
}
.address-value {
font-size: 22px;
color: var(--danger);
font-weight: 800;
}
.loading {
text-align: center;
padding: 25px;
display: none;
}
.spinner {
border: 5px solid rgba(0, 0, 0, 0.1);
border-top: 5px solid var(--primary);
border-radius: 50%;
width: 50px;
height: 50px;
animation: spin 1s linear infinite;
/* animation和@keyframes连用 */
margin: 0 auto 20px;
}
@keyframes spin {
/* spin是动画名称,用来实现自转 */
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.error {
color: var(--danger);
background: rgba(231, 76, 60, 0.1);
padding: 18px;
border-radius: 10px;
margin-top: 20px;
display: none;
border-left: 4px solid var(--danger);
font-weight: 500;
}
footer {
text-align: center;
padding: 20px;
color: #666;
font-size: 15px;
border-top: 1px solid #eee;
}
@media (max-width: 768px) {
.content {
flex-direction: column;
}
.input-section, .map-section {
width: 100%;
}
h1 {
font-size: 28px;
}
}
/* 响应式设计 */
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Font Awesome 图标库 的 CSS 文件地址 -->
<!-- 里面提供了大量可自定义图标 -->
</head>
<body>
<div class="container">
<header>
<h1><i class="fas fa-map-marked-alt"></i> 腾讯地图逆地址解析</h1>
<!-- 这里的i标签用来包裹字体图标(如 Font Awesome),成为图标占位符 -->
<!-- 一般斜体不用i,用em或者font-style: italic; -->
<!-- 如果用i除了上面一种情况外,还有就是i标签包裹的内容语气或者性质与旁文不同 -->
<div class="subtitle">GPS经纬度转换为详细地址信息</div>
</header>
<div class="content">
<div class="input-section">
<div class="input-group">
<label for="latitude"><i class="fas fa-latitude"></i> 纬度</label>
<input type="text" id="latitude" placeholder="例如:39.908823">
</div>
<div class="input-group">
<label for="longitude"><i class="fas fa-longitude"></i> 经度</label>
<input type="text" id="longitude" placeholder="例如:116.397470">
</div>
<div class="button-group">
<button id="parseBtn"><i class="fas fa-search-location"></i> 解析地址</button>
<button id="getLocationBtn"><i class="fas fa-location-arrow"></i> 获取当前位置</button>
</div>
<div class="loading" id="loading">
<div class="spinner"></div>
<p>正在解析地址信息,请稍候...</p>
</div>
<div class="error" id="error">
<i class="fas fa-exclamation-circle"></i>
<span id="errorMsg"></span>
</div>
<div class="result-section" id="resultSection" style="display: none;">
<div class="result-title">
<i class="fas fa-map-marker-alt"></i>
<span>解析结果</span>
</div>
<div class="result-grid">
<div class="result-item">
<div class="result-label"><i class="fas fa-road"></i> 完整地址</div>
<div class="result-value address-value" id="fullAddress">-</div>
</div>
<div class="result-item">
<div class="result-label"><i class="fas fa-flag"></i> 国家</div>
<div class="result-value" id="nation">-</div>
</div>
<div class="result-item">
<div class="result-label"><i class="fas fa-map"></i> 省份</div>
<div class="result-value" id="province">-</div>
</div>
<div class="result-item">
<div class="result-label"><i class="fas fa-city"></i> 城市</div>
<div class="result-value" id="city">-</div>
</div>
<div class="result-item">
<div class="result-label"><i class="fas fa-building"></i> 区县</div>
<div class="result-value" id="district">-</div>
</div>
<div class="result-item">
<div class="result-label"><i class="fas fa-street-view"></i> 街道</div>
<div class="result-value" id="street">-</div>
</div>
</div>
</div>
</div>
<div class="map-section">
<div id="map"></div>
</div>
</div>
<footer>
<div>本服务使用腾讯地图API | 逆地址解析功能</div>
<div style="margin-top: 8px; font-size: 13px; color: #888;">
<i class="fas fa-info-circle"></i> 请确保在HTTP/HTTPS协议下使用
</div>
</footer>
</div>
以下是JavaScript部分
<script>
// 初始化地图
let map;
let marker;
let geocoder;
// 页面加载完成后初始化地图
window.onload = function() {
// 检查是否在HTTP/HTTPS协议下运行
if (window.location.protocol === 'file:') {
showError('腾讯地图API不支持在本地文件协议(file://)下使用,请在HTTP/HTTPS协议下运行此页面');
return;
}
// 初始化地图
initMap();
};
function initMap() {
try {
// try捕获错误,无错则跳过catch
// 默认坐标 - 北京
const center = new TMap.LatLng(39.908823, 116.397470);
// 初始化地图
map = new TMap.Map('map', {
// 腾讯地图创建地图实例
// 格式为map = new TMap.Map(container, options);
// option除了以下还有rotation,pitch
center: center,
zoom: 15,
// zoom:(3-20)表示地图的缩放级别,数值越小地图显示范围越大
viewMode: '2D'
});
// 添加标记
marker = new TMap.MultiMarker({
// 创建多个标记点实例
map: map,
// 创建的标记绑在map实例上
styles: {
"marker": new TMap.MarkerStyle({
width: 25,
height: 35,
anchor: {x: 12.5, y: 35},
// 定位点,用于指定标记图片的哪个点与实际坐标(经纬度)对齐
src: 'https://mapapi.qq.com/web/lbs/javascriptGL/demo/img/marker.png'
})
},
geometries: [{
id: 'location',
styleId: 'marker',
position: center
}]
});
// 初始化地理编码服务TMap.service.Geocoder()
// 它是腾讯地图 API 提供的一个服务类,封装了地理编码相关的功能
geocoder = new TMap.service.Geocoder();
} catch (e) {
// catch处理错误
showError(`地图初始化失败: ${e.message}`);
}
}
// 获取DOM元素
const latitudeInput = document.getElementById('latitude');
const longitudeInput = document.getElementById('longitude');
const parseBtn = document.getElementById('parseBtn');
// 解析地址btn
const getLocationBtn = document.getElementById('getLocationBtn');
// 获取当前地址的btn
const resultSection = document.getElementById('resultSection');
// 解析结果
const loading = document.getElementById('loading');
const errorElement = document.getElementById('error');
const errorMsg = document.getElementById('errorMsg');
// 更新结果展示
function updateResults(data) {
document.getElementById('fullAddress').textContent = data.address || '未知';
document.getElementById('nation').textContent = data.address_component.nation || '未知';
document.getElementById('province').textContent = data.address_component.province || '未知';
document.getElementById('city').textContent = data.address_component.city || '未知';
document.getElementById('district').textContent = data.address_component.district || '未知';
document.getElementById('street').textContent = data.address_component.street || '未知';
resultSection.style.display = 'block';
}
// 显示错误信息
function showError(message) {
errorMsg.textContent = message;
errorElement.style.display = 'flex';
setTimeout(() => {
errorElement.style.display = 'none';
}, 8000);
}
// 逆地址解析函数
function reverseGeocode(lat, lng) {
// 显示加载状态
loading.style.display = 'block';
resultSection.style.display = 'none';
errorElement.style.display = 'none';
// 确保地理编码服务已初始化
if (!geocoder) {
try {
geocoder = new TMap.service.Geocoder();
} catch (e) {
loading.style.display = 'none';
showError(`地理编码服务初始化失败: ${e.message}`);
return;
}
}
// 调用逆地址解析
geocoder.getAddress({ location: new TMap.LatLng( lat, lng ) })
// 接收经纬度地址
// getAddress() 是一个异步方法,返回一个 Promise 对象,then() 用于处理请求成功的情况
.then((result) => {
// 隐藏加载状态
loading.style.display = 'none';
if (result.status === 0) {
// status === 0表示解析成功,是腾讯地图api的规定
// 更新结果展示
updateResults(result.result);
// 更新地图位置
const newPosition = new TMap.LatLng(lat, lng);
map.setCenter(newPosition);
marker.setGeometries([{
// 更新标记点
id: 'location',
styleId: 'marker',
position: newPosition
}]);
} else {
showError(`解析失败: ${result.message}`);
}
})
.catch((error) => {
loading.style.display = 'none';
showError(`请求失败: ${error.message}`);
});
}
// 解析按钮点击事件
parseBtn.addEventListener('click', () => {
const lat = parseFloat(latitudeInput.value.trim());
const lng = parseFloat(longitudeInput.value.trim());
if (isNaN(lat) || isNaN(lng)) {
showError('请输入有效的经纬度数值');
return;
}
if (lat < -90 || lat > 90) {
showError('纬度范围应在-90到90之间');
return;
}
if (lng < -180 || lng > 180) {
showError('经度范围应在-180到180之间');
return;
}
reverseGeocode(lat, lng);
});
// 获取当前位置按钮点击事件
getLocationBtn.addEventListener('click', () => {
if (!navigator.geolocation) {
showError('您的浏览器不支持地理位置服务');
return;
}
// 显示加载状态
loading.style.display = 'block';
resultSection.style.display = 'none';
errorElement.style.display = 'none';
navigator.geolocation.getCurrentPosition(
// 这是浏览器提供的 获取用户当前地理位置 的 API
// 格式navigator.geolocation.getCurrentPosition(定位成功时执行的回调函数(必填),失败时的,配置)
(position) => {
// coords是coordinate的缩写,用到latitude这些表位置的参数时必须用到它
const lat = position.coords.latitude;
const lng = position.coords.longitude;
// 更新输入框
latitudeInput.value = lat.toFixed(6);
longitudeInput.value = lng.toFixed(6);
// 进行逆地址解析
reverseGeocode(lat, lng);
},
(error) => {
loading.style.display = 'none';
let errorMessage;
switch(error.code) {
case error.PERMISSION_DENIED:
errorMessage = "用户拒绝了位置请求";
break;
case error.POSITION_UNAVAILABLE:
errorMessage = "位置信息不可用";
break;
case error.TIMEOUT:
errorMessage = "获取位置超时";
break;
default:
errorMessage = "烦死了";
}
showError(`获取位置失败: ${errorMessage}`);
},
{
enableHighAccuracy: true,
// 启用高精度地位
timeout: 10000,
// 超时时间
maximumAge: 300000
// 允许缓存位置的最大事件
}
);
});
// 示例坐标(北京天安门)
// latitudeInput.value = "39.908823";
// longitudeInput.value = "116.397470";
</script>
</body>
</html>
(编者水平有限,还请大家多多指教)