天地图实现收货地址定位

复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>选择收货地址</title>
<style>
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
body {
  background-color: #f5f7fa;
  font-size: 15px;
  color: #333;
  padding-bottom: 84px;
}
/* 顶部搜索栏 */
.search-bar {
  background: #fff;
  padding: 12px 16px;
  display: flex;
  gap: 10px;
  align-items: center;
  position: sticky;
  top:0;
  z-index:100;
  box-shadow: 0 1px 6px rgba(0,0,0,0.05);
}
.search-bar input {
  flex:1;
  border: 1px solid #e5e7eb;
  border-radius: 24px;
  padding: 10px 16px;
  font-size:15px;
}
.search-bar input:focus {
  outline:none;
  border-color:#0066cc;
}
.search-bar button {
  background:#0066cc;
  color:#fff;
  border:none;
  border-radius:24px;
  padding: 10px 14px;
  font-size:14px;
}
/* 地图容器 + 中心定位大头针(打车样式) */
.map-wrap {
  position:relative;
  width:100%;
  height: 200px;
}
#mapDiv {
  width:100%;
  height:100%;
}
.map-pin {
  position:absolute;
  left:50%;
  top:50%;
  transform: translate(-50%, -100%);
  font-size:36px;
  pointer-events:none;
  z-index:900;
}
/* 重新定位悬浮按钮 */
.btn-refresh-loc {
  position:absolute;
  right:14px;
  bottom:14px;
  width:44px;
  height:44px;
  border-radius:50%;
  background:#fff;
  box-shadow:0 2px 8px rgba(0,0,0,0.15);
  border:none;
  font-size:20px;
  z-index:900;
}
/* 卡片 */
.card {
  background:#fff;
  border-radius:12px;
  box-shadow: 0 2px 12px rgba(0,0,0,0.06);
  margin:12px 12px;
  overflow:hidden;
}
.card-header {
  padding:14px 16px;
  font-size:16px;
  font-weight:600;
  border-bottom:1px solid #f2f2f2;
}
.card-body {
  padding:16px;
}
.form-item {
  margin-bottom:14px;
}
.form-item label {
  display:block;
  font-size:14px;
  color:#666;
  margin-bottom:6px;
}
.form-item input {
  width:100%;
  border:1px solid #e5e7eb;
  border-radius:10px;
  padding:8px 14px;
  font-size:15px;
}
.form-item input:focus {
  outline:none;
  border-color:#0066cc;
}
.row-three {
  display:flex;
  gap:8px;
}
.row-three .form-item {
  flex:1;
  margin-bottom:0;
}
.row-three input {
  padding:10px 8px;
  font-size:14px;
}
/* 底部提交 */
.btn-submit {
  position:fixed;
  left:16px;
  right:16px;
  bottom:16px;
  background:#ff6b35;
  color:#fff;
  border:none;
  border-radius:12px;
  padding:14px 0;
  font-size:17px;
  font-weight:600;
}
.btn-submit:active {
  background:#e65c2b;
}
/* Toast */
.toast {
  position:fixed;
  left:50%;
  top:40%;
  transform:translate(-50%,-50%);
  background:rgba(0,0,0,0.72);
  color:#fff;
  padding:10px 18px;
  border-radius:8px;
  font-size:14px;
  z-index:9999;
  display:none;
}
.tip-desc {
  text-align:center;
  color:#999;
  font-size:13px;
  padding:8px 0;
}
</style>
<!-- 天地图JS4.0 官方引入 -->
<script src="https://api.tianditu.gov.cn/api?v=4.0&tk=98dbc34f1a1a583022c722ff951a465d"></script>
</head>
<body>
<!-- 搜索区域 -->
<div class="search-bar">
  <input id="searchInput" placeholder="输入地址搜索,例如:重庆市渝北区XX小区">
  <button id="searchBtn">搜索</button>
</div>

<!-- 地图区域 打车风格:中心大头针 -->
<div class="map-wrap">
  <div id="mapDiv"></div>
  <div class="map-pin">📍</div>
  <button class="btn-refresh-loc" id="refreshLocBtn">🎯</button>
</div>
<div class="tip-desc">拖动地图选择位置,自动识别地址</div>

<!-- 收货表单 -->
<div class="card">
  <div class="card-header">收货信息</div>
  <div class="card-body">
    <div class="form-item">
      <label>收货人</label>
      <input type="text" id="name" placeholder="请输入姓名">
    </div>
    <div class="form-item">
      <label>手机号码</label>
      <input type="tel" id="phone" placeholder="请输入手机号">
    </div>
    <div class="row-three">
      <div class="form-item">
        <label>省</label>
        <input type="text" id="province" readonly>
      </div>
      <div class="form-item">
        <label>市</label>
        <input type="text" id="city" readonly>
      </div>
      <div class="form-item">
        <label>区/县</label>
        <input type="text" id="district" readonly>
      </div>
    </div>
    <div class="form-item" style="margin-top:14px;">
      <label>详细地址</label>
      <input type="text" id="address" placeholder="街道、小区、门牌号">
    </div>
  </div>
</div>

<button class="btn-submit" id="submitBtn">保存收货地址</button>
<div class="toast" id="toast"></div>

<script>
const TK = "98dbc34f1a1a583022c722ff951a465d";
let map;
const toastDom = document.getElementById('toast');
const searchInput = document.getElementById('searchInput');
const searchBtn = document.getElementById('searchBtn');
const refreshLocBtn = document.getElementById('refreshLocBtn');

// toast提示
function showToast(msg, time=2000) {
  toastDom.innerText = msg;
  toastDom.style.display = "block";
  setTimeout(()=>{
    toastDom.style.display = "none";
  }, time)
}

// 初始化地图
function initMap() {
  map = new T.Map("mapDiv");
  const initCenter = new T.LngLat(116.404,39.915);
  map.centerAndZoom(initCenter,12);
  // 地图拖动结束,取中心点经纬度,逆解析地址(核心!打车模式)
  map.addEventListener("moveend", function(){
    const center = map.getCenter();
    getAddressByLngLat(center.lng, center.lat);
  })
}

// 【逆地理编码】经纬度 → 省市区地址(官方接口)
function getAddressByLngLat(lon, lat) {
  const url = `https://api.tianditu.gov.cn/geocoder?postStr={"lon":${lon},"lat":${lat},"ver":1}&type=geocode&tk=${TK}`;
  fetch(url)
  .then(res=>res.json())
  .then(json=>{
    if(json.status !== "0"){
      return;
    }
    const r = json.result;
    document.getElementById("province").value = r.addressComponent.province || "";
    document.getElementById("city").value = r.addressComponent.city || "";
	if(r.addressComponent.city=="")
	{
	   document.getElementById("city").value = r.addressComponent.province || "";
	}
    document.getElementById("district").value = r.addressComponent.county || "";
    document.getElementById("address").value = r.addressComponent.address || "";
  })
  .catch(err=>{
    console.error("逆编码错误",err);
  })
}

// 【地理编码】地址搜索 → 经纬度(官方接口)
function searchAddress(keyword) {
  if(!keyword.trim()) return showToast("请输入地址");
  showToast("正在搜索...",9999);
  const url = `https://api.tianditu.gov.cn/geocoder?ds={"keyWord":"${keyword}"}&tk=${TK}`;
  fetch(url)
  .then(res=>res.json())
  .then(json=>{
    if(json.status !== "0"){
      showToast("未找到该地址");
      return;
    }
    const loc = json.location;
    const point = new T.LngLat(loc.lon, loc.lat);
    map.centerAndZoom(point,16);
    showToast("定位成功");
  })
  .catch(err=>{
    showToast("搜索失败");
    console.error(err);
  })
}

// GPS定位(自动定位 + 重新定位按钮共用)
function getGpsLocation() {
  if(!navigator.geolocation){
    showToast("浏览器不支持定位");
    return;
  }
  showToast("正在获取您的位置...",9999);
  navigator.geolocation.getCurrentPosition(pos=>{
    const lon = pos.coords.longitude;
    const lat = pos.coords.latitude;
    const point = new T.LngLat(lon, lat);
    map.centerAndZoom(point,16);
    showToast("定位成功");
  },err=>{
    let msg;
    if(err.code === 1) msg="定位权限被拒绝,请在浏览器允许位置权限";
    else if(err.code ===2) msg="定位失败,信号弱";
    else msg="定位超时";
    showToast(msg);
  },{enableHighAccuracy:true,timeout:12000})
}

// 保存地址
document.getElementById('submitBtn').onclick = function(){
  const data = {
    name: document.getElementById('name').value.trim(),
    phone: document.getElementById('phone').value.trim(),
    province: document.getElementById('province').value,
    city: document.getElementById('city').value,
    district: document.getElementById('district').value,
    address: document.getElementById('address').value
  }
  if(!data.name) return showToast("请填写收货人姓名");
  if(!data.phone) return showToast("请填写手机号");
  if(!data.address) return showToast("请选择地址");
  showToast("地址保存成功!");
  console.log("收货地址数据", data);
  // 这里可以ajax提交后端
}

// 绑定事件
window.onload = function(){
  initMap();
  // 页面加载【自动触发GPS定位】
  getGpsLocation();
  // 搜索按钮
  searchBtn.onclick = ()=> searchAddress(searchInput.value);
  // 回车搜索
  searchInput.onkeydown = (e)=>{
    if(e.key === 'Enter') searchAddress(searchInput.value);
  }
  // 重新定位按钮
  refreshLocBtn.onclick = getGpsLocation;
}
</script>
</body>
</html>

本文介绍一个基于天地图API的收货地址选择页面,集成搜索、地图定位、自动逆地理编码功能。用户可通过输入地址搜索或拖动地图选择位置,系统自动识别省市区及详细地址。支持GPS定位与重新定位,表单填写后可保存收货信息,界面简洁,适配移动端,提升地址录入效率。

相关推荐
心梦轻舞1 小时前
从 14 道面试题,彻底搞懂 Event Loop 与 Vue2 nextTick 底层原理
javascript
去伪存真1 小时前
架构思考与演进:如何彻底破解 RAG 切块大小与语义完整性的工程悖论?
前端·agent
馒头不想说话1 小时前
AI剪辑工具降低创作门槛
前端
paopaokaka_luck1 小时前
社区服务平台(加权协同过滤推荐、Jieba中文词频分析、WebSocket实时聊天、求助处理闭环、 活动积分闭环、ECharts多维分析)
java·前端·spring boot·mysql·echarts·mybatis
墨林陌2 小时前
翻完 DeepSeek 的 GitHub 仓库,我发现 V5 的发布路已经修好了
前端
Antruly2 小时前
uvscope:Web 调试界的瑞士军刀
前端
计算机魔术师2 小时前
Anthropic S-1 披露:半年前发布的模型,已贡献不了多少收入了
前端
qq_340040882 小时前
idea2021版,vue项目的package.json不展示scripts的绿色箭头
javascript·vue.js·json
qq_364682152 小时前
录音APP怎么切换语言?多语言版本如何使用
java·服务器·前端