在电商行业蓬勃发展的今天,物流信息查询已成为人们日常生活中的重要需求。本文将详细介绍如何基于高德地图 API 利用 HTML + JavaScript 实现物流轨迹跟踪系统的开发。
效果演示



项目概述
本项目主要包含以下核心功能:
- 地图初始化与展示
- 运单号查询功能
- 物流轨迹可视化显示
准备工作
-
注册高德开放平台账号,创建应用并获取API Key。
-
引入高德地图 API (将 API_Key 替换为自己的)和德地图 UI 组件库
html
<script src="https://webapi.amap.com/maps?v=2.0&key=API_Key"></script>
<script src="https://webapi.amap.com/ui/1.1/main.js"></script>
页面结构与样式设计
创建 HTML 结构
页面主要包含两个核心区域:
- container:用于承载地图展示的核心区域
- panel:右上角的操作面板,包含输入框、查询按钮和物流信息展示区
html
<div id="container"></div>
<div id="panel">
<h3>物流轨迹查询</h3>
<div class="input-group">
<input type="text" id="orderNumber" placeholder="请输入运单号">
</div>
<button id="queryBtn">查询轨迹</button>
<div id="logistics-info"></div>
</div>
设计 CSS 样式
地图容器样式
css
#container {
width: 100%;
height: 100vh;
position: relative;
}
操作面板样式
css
#panel {
position: absolute;
top: 10px;
right: 10px;
width: 300px;
background: white;
padding: 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.2);
z-index: 999;
border-radius: 5px;
}
.input-group {
margin-bottom: 10px;
}
input, button {
padding: 8px;
width: 100%;
box-sizing: border-box;
}
button {
background: #1E90FF;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background: #1874CD;
}
#logistics-info {
margin-top: 10px;
font-size: 14px;
max-height: 300px;
overflow-y: auto;
}
.info-item {
margin-bottom: 5px;
padding-bottom: 5px;
border-bottom: 1px solid #eee;
}
.info-time {
color: #888;
font-size: 12px;
}
.info-content {
color: #333;
}
核心功能实现
初始化地图
js
var map = new AMap.Map('container', {
zoom: 10, // 缩放级别
center: [116.397428, 39.90923], // 中心点坐标(北京)
viewMode: '2D' // 使用2D视图
});
获取物流数据
这里只是示例,模拟了不同运单号返回不同数据,实际应用中可以通过请求后端 API 获取真实数据。
js
function getLogisticsData(orderNumber) {
if (orderNumber === "123456") {
return {
status: "success",
company: "顺丰速运",
number: orderNumber,
steps: [
{
time: "2023-05-01 08:00:00",
location: [116.404, 39.915],
content: "快件已到达【北京朝阳集散中心】"
},
// ...
]
};
} else if (orderNumber === "654321") {
return {
status: "success",
company: "中通快递",
number: orderNumber,
steps: [
// ...
]
};
} else {
return {
status: "error",
message: "未找到该运单号的物流信息"
};
}
}
清除地图上的轨迹和标记
js
function clearMap() {
if (polyline) {
map.remove(polyline);
polyline = null;
}
if (markers.length > 0) {
map.remove(markers);
markers = [];
}
}
显示物流轨迹
js
function showLogisticsTrack(data) {
// 清除之前的轨迹
clearMap();
// 更新物流信息显示
var infoDiv = document.getElementById('logistics-info');
infoDiv.innerHTML = '';
if (data.status === "error") {
infoDiv.innerHTML = '<div class="info-item">' + data.message + '</div>';
return;
}
// 显示物流公司信息
infoDiv.innerHTML += '<div class="info-item"><strong>' + data.company + '</strong> 运单号: ' + data.number + '</div>';
// 提取轨迹点坐标
var lineArr = [];
// 按时间顺序排序(确保最早的步骤在最前面)
data.steps.sort(function(a, b) {
return new Date(a.time) - new Date(b.time);
});
// 添加标记和轨迹线
data.steps.forEach(function(step, index) {
// 添加到轨迹线
lineArr.push(step.location);
// 创建标记
var marker = new AMap.Marker({
position: step.location,
map: map,
content: '<div style="background: #1E90FF; color: white; border-radius: 50%; width: 20px; height: 20px; text-align: center; line-height: 20px;">' + (index + 1) + '</div>',
offset: new AMap.Pixel(-10, -10)
});
// 信息窗口内容
var infoContent = '<div style="padding: 5px;">' +
'<div style="font-weight: bold;">步骤 ' + (index + 1) + '</div>' +
'<div>' + step.content + '</div>' +
'<div style="color: #888; font-size: 12px;">' + step.time + '</div>' +
'</div>';
// 点击标记显示信息窗口
marker.on('click', function() {
new AMap.InfoWindow({
content: infoContent,
offset: new AMap.Pixel(0, -30)
}).open(map, step.location);
});
markers.push(marker);
// 添加物流信息到面板
infoDiv.innerHTML += '<div class="info-item">' +
'<div class="info-time">' + step.time + '</div>' +
'<div class="info-content">' + step.content + '</div>' +
'</div>';
});
// 绘制轨迹线
polyline = new AMap.Polyline({
path: lineArr,
isOutline: true,
outlineColor: '#ffeeff',
borderWeight: 1,
strokeColor: "#3366FF",
strokeOpacity: 1,
strokeWeight: 5,
strokeStyle: "solid",
lineJoin: 'round',
lineCap: 'round',
zIndex: 50
});
map.add(polyline);
// 调整视图以适应轨迹
map.setFitView(polyline);
}
查询功能实现
输入运单号,点击【查询轨迹】按钮获取输入框中的运单号,根据运单号获取物流数据,显示物流轨迹。
js
document.getElementById('queryBtn').addEventListener('click', function() {
var orderNumber = document.getElementById('orderNumber').value.trim();
if (!orderNumber) return;
var logisticsData = getLogisticsData(orderNumber);
showLogisticsTrack(logisticsData);
});
完整代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>物流轨迹跟踪系统</title>
<style>
body, html {
margin: 0;
padding: 0;
}
#container {
width: 100%;
height: 100vh;
position: relative;
}
#panel {
position: absolute;
top: 10px;
right: 10px;
width: 300px;
background: white;
padding: 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.2);
z-index: 999;
border-radius: 5px;
}
.input-group {
margin-bottom: 10px;
}
input, button {
padding: 8px;
width: 100%;
box-sizing: border-box;
}
button {
background: #1E90FF;
color: white;
border: none;
cursor: pointer;
}
button:hover {
background: #1874CD;
}
#logistics-info {
margin-top: 10px;
font-size: 14px;
max-height: 300px;
overflow-y: auto;
}
.info-item {
margin-bottom: 5px;
padding-bottom: 5px;
border-bottom: 1px solid #eee;
}
.info-time {
color: #888;
font-size: 12px;
}
.info-content {
color: #333;
}
</style>
</head>
<body>
<div id="container"></div>
<div id="panel">
<h3>物流轨迹查询</h3>
<div class="input-group">
<input type="text" id="orderNumber" placeholder="请输入运单号">
</div>
<button id="queryBtn">查询轨迹</button>
<div id="logistics-info"></div>
</div>
<!-- 引入高德地图API -->
<script src="https://webapi.amap.com/maps?v=2.0&key=API_Key"></script>
<!-- 引入高德地图UI组件库 -->
<script src="https://webapi.amap.com/ui/1.1/main.js"></script>
<script>
// 初始化地图
var map = new AMap.Map('container', {
zoom: 10, // 缩放级别
center: [116.397428, 39.90923], // 中心点坐标(北京)
viewMode: '2D' // 使用2D视图
});
// 轨迹线
var polyline = null;
// 轨迹点标记
var markers = [];
// 模拟物流数据(实际应用中应从后端API获取)
function getLogisticsData(orderNumber) {
if (orderNumber === "123456") {
return {
status: "success",
company: "顺丰速运",
number: orderNumber,
steps: [
{
time: "2023-05-01 08:00:00",
location: [116.404, 39.915],
content: "快件已到达【北京朝阳集散中心】"
},
{
time: "2023-05-01 10:30:00",
location: [116.408, 39.925],
content: "快件已从【北京朝阳集散中心】发出,下一站【北京海淀集散中心】"
},
{
time: "2023-05-01 14:15:00",
location: [116.300, 39.960],
content: "快件已到达【北京海淀集散中心】"
},
{
time: "2023-05-02 09:00:00",
location: [116.310, 39.980],
content: "快件正在派送中,派件员:张三,电话:138****1234"
},
{
time: "2023-05-02 11:30:00",
location: [116.315, 39.985],
content: "快件已签收,签收人:李四"
}
]
};
} else if (orderNumber === "654321") {
return {
status: "success",
company: "中通快递",
number: orderNumber,
steps: [
{
time: "2023-05-10 13:20:00",
location: [121.4737, 31.2304],
content: "快件已从【上海虹口集散中心】发出"
},
{
time: "2023-05-11 08:45:00",
location: [120.1551, 30.2741],
content: "快件已到达【杭州集散中心】"
},
{
time: "2023-05-11 16:30:00",
location: [120.2108, 30.2468],
content: "快件已从【杭州集散中心】发出,下一站【杭州西湖分部】"
}
]
};
} else {
return {
status: "error",
message: "未找到该运单号的物流信息"
};
}
}
// 清除地图上的轨迹和标记
function clearMap() {
if (polyline) {
map.remove(polyline);
polyline = null;
}
if (markers.length > 0) {
map.remove(markers);
markers = [];
}
}
// 显示物流轨迹
function showLogisticsTrack(data) {
// 清除之前的轨迹
clearMap();
// 更新物流信息显示
var infoDiv = document.getElementById('logistics-info');
infoDiv.innerHTML = '';
if (data.status === "error") {
infoDiv.innerHTML = '<div class="info-item">' + data.message + '</div>';
return;
}
// 显示物流公司信息
infoDiv.innerHTML += '<div class="info-item"><strong>' + data.company + '</strong> 运单号: ' + data.number + '</div>';
// 提取轨迹点坐标
var lineArr = [];
// 按时间顺序排序(确保最早的步骤在最前面)
data.steps.sort(function(a, b) {
return new Date(a.time) - new Date(b.time);
});
// 添加标记和轨迹线
data.steps.forEach(function(step, index) {
// 添加到轨迹线
lineArr.push(step.location);
// 创建标记
var marker = new AMap.Marker({
position: step.location,
map: map,
content: '<div style="background: #1E90FF; color: white; border-radius: 50%; width: 20px; height: 20px; text-align: center; line-height: 20px;">' + (index + 1) + '</div>',
offset: new AMap.Pixel(-10, -10)
});
// 信息窗口内容
var infoContent = '<div style="padding: 5px;">' +
'<div style="font-weight: bold;">步骤 ' + (index + 1) + '</div>' +
'<div>' + step.content + '</div>' +
'<div style="color: #888; font-size: 12px;">' + step.time + '</div>' +
'</div>';
// 点击标记显示信息窗口
marker.on('click', function() {
new AMap.InfoWindow({
content: infoContent,
offset: new AMap.Pixel(0, -30)
}).open(map, step.location);
});
markers.push(marker);
// 添加物流信息到面板
infoDiv.innerHTML += '<div class="info-item">' +
'<div class="info-time">' + step.time + '</div>' +
'<div class="info-content">' + step.content + '</div>' +
'</div>';
});
// 绘制轨迹线
polyline = new AMap.Polyline({
path: lineArr,
isOutline: true,
outlineColor: '#ffeeff',
borderWeight: 1,
strokeColor: "#3366FF",
strokeOpacity: 1,
strokeWeight: 5,
strokeStyle: "solid",
lineJoin: 'round',
lineCap: 'round',
zIndex: 50
});
map.add(polyline);
// 调整视图以适应轨迹
map.setFitView(polyline);
}
// 查询按钮点击事件
document.getElementById('queryBtn').addEventListener('click', function() {
var orderNumber = document.getElementById('orderNumber').value.trim();
if (!orderNumber) return;
var logisticsData = getLogisticsData(orderNumber);
showLogisticsTrack(logisticsData);
});
</script>
</body>
</html>