简介
实现在 web 浏览器端用原生 JS 在高德地图上实现轨迹回放的功能,并在回放的过程中实时更新该坐标的详细信息
效果gif
来源
在官网的demo上加了展示信息的小弹窗,实现原理:就是在卡车移动的时候实时更新信息到dom上
实现步骤
- 引入高德地图 JS
<script src="https://webapi.amap.com/maps?v=1.4.15&key=" + "自己申请的Key值"></script>
- 画html
<body>
<div id="container">
<div id="btn-card">
<span class="operate">轨迹回放:</span>
<button class="btn" onclick="start()">开始</button>
<button class="btn" onclick="pause()">暂停</button>
<button class="btn" onclick="reset()">重置</button>
</div>
</div>
<div id="tips">
<span id="license"></span>
<span id="speed"></span>
<span id="longitude"></span>
<span id="latitude"></span>
<span id="time"></span>
</div>
</body
- 模拟后台数据,创建地图元素
<script>
// 这是模拟后台返回的数据,包括每个点的具体信息
var data = [
{ longitude: 116.478935, latitude: 39.997761, license: '陕KE1675', speed: '57.2KM/H', time: '2021-06-07 16:21:12' },
{ longitude: 116.478939, latitude: 39.997825, license: '陕KE1675', speed: '56.5KM/H', time: '2021-06-07 16:25:21' },
{ longitude: 116.478912, latitude: 39.998549, license: '陕KE1675', speed: '48.3KM/H', time: '2021-06-07 16:51:28' },
{ longitude: 116.479282, latitude: 39.998561, license: '陕KE1675', speed: '65.6KM/H', time: '2021-06-07 17:21:30' },
{ longitude: 116.479658, latitude: 39.998528, license: '陕KE1675', speed: '39.1KM/H', time: '2021-06-07 17:20:38' },
{ longitude: 116.480151, latitude: 39.998453, license: '陕KE1675', speed: '53.7KM/H', time: '2021-06-07 19:01:42' },
{ longitude: 116.482362, latitude: 39.997718, license: '陕KE1675', speed: '57.8KM/H', time: '2021-06-07 20:31:45' },
{ longitude: 116.483633, latitude: 39.998935, license: '陕KE1675', speed: '59.1KM/H', time: '2021-06-07 21:28:50' },
{ longitude: 116.483671, latitude: 39.998968, license: '陕KE1675', speed: '70.2KM/H', time: '2021-06-07 22:45:58' },
{ longitude: 116.484648, latitude: 39.999861, license: '陕KE1675', speed: '68.6KM/H', time: '2021-06-07 23:23:00' }
]
/*
构造函数介绍:
AMap.LngLat(lng:Number,lat:Number,noAutofix:bool): 构造一个地理坐标对象
lng、lat分别代表经度、纬度值;
noAutoFix表示是否自动将经度修正到 [-180,180] 区间内,缺省为false,此时会自动修正,比如传入[190,30],会被自动修正为[-170,30],noAutoFix为true时不会自动修正
AMap.Pixel(x:Number,y:Number): 构造一个像素坐标对象
x方向坐标,y方向坐标
*/
/**
* map: 地图容器
* marker: 移动的汽车
* lineArr: 轨迹节点的坐标数组
* polyline: 整条轨迹
* passedPolyline: 已经移动过的轨迹
* infoTip: 信息展示tips
*/
var map, marker, lineArr, polyline, passedPolyline, infoTip;
// 当前是否正在移动
var movingFlag = false;
initMap(data);
function initMap(data) {
lineArr = data.map(item => [item.longitude, item.latitude]);
map = new AMap.Map('container', {
// Boolean: 是否监控地图容器尺寸变化,默认值为false
resizeEnable: true,
// LngLat: 地图中心点坐标值,数组类型的格式也可以
center: [116.397428, 39.90923],
// Number: 地图显示的缩放级别,若center与level未赋值,地图初始化默认显示用户所在城市范围
zoom: 11
});
// 创建汽车
marker = new AMap.Marker({
// Map: 要显示该marker的地图对象
map: map,
// LngLat: 点标记在地图上显示的位置,默认为地图中心点,数组类型的格式也可以
// 或 position: new AMap.LngLat(116.478935, 39.997761),
position: lineArr[0],
// String/Icon: 需在点标记中显示的图标。可以是一个本地图标地址,或者Icon对象。有合法的content内容时,此属性无效
icon: "https://webapi.amap.com/images/car.png",
/*
Pixel: 点标记显示位置偏移量,默认值为Pixel(-10,-34)
Marker指定position后,默认以marker左上角位置为基准点,对准所给定的position位置,若需使marker指定位置对准在position处,需根据marker的尺寸设置一定的偏移量
*/
offset: new AMap.Pixel(-26, -13),
// Boolean: 是否自动旋转。点标记在使用moveAlong动画时,路径方向若有变化,点标记是否自动调整角度,默认为false。广泛用于自动调节车辆行驶方向
autoRotation: true,
// Number: 点标记的旋转角度,广泛用于改变车辆行驶方向
angle: -90,
});
// 绘制整条轨迹
polyline = new AMap.Polyline({
// Map: 要显示该polyline的地图对象
map: map,
// Array: 折线的节点坐标数组
path: lineArr,
// Boolean: 是否延路径显示白色方向箭头,默认false。Canvas绘制时有效,建议折线宽度大于6时使用
showDir: true,
// String: 线条颜色,使用16进制颜色代码赋值。默认值为#006600
strokeColor: "#28F",
// Number: 线条透明度,取值范围[0,1],0表示完全透明,1表示不透明。默认为0.9
strokeOpacity: 1,
// Number: 线条宽度,单位:像素
strokeWeight: 6,
// String: 线样式,实线:solid,虚线:dashed
strokeStyle: "solid"
});
// 创建信息展示tip
infoTip = new AMap.InfoWindow({
isCustom: true, // 使用自定义窗体
content: document.getElementById('tips'),
offset: new AMap.Pixel(16, -45)
});
// 已经移动过的轨迹
passedPolyline = new AMap.Polyline({
map: map,
strokeColor: "#AF5",
strokeWeight: 6,
strokeStyle: "dashed"
});
}
</script>
- 用户行为控制,监听移动事件
<script>
function start() {
if (!movingFlag) {
/*
moveAlong(path:Array, speed:Number, f:Function, circlable:Boolean)
以指定的速度,点标记沿指定的路径移动。
path: 为轨迹路径的经纬度对象的数组;
speed:为指定速度,单位:千米/小时,不可为0
f: 为变化曲线函数,缺省为function(k){return k}
circlable: 表明是否循环执行动画,默认为false
*/
marker.moveAlong(lineArr, 500);
movingFlag = true;
} else {
// 恢复点标记的动画效果
marker.resumeMove();
}
}
function pause() {
if (movingFlag) {
// 暂定点标记的动画效果
marker.pauseMove();
}
}
function reset() {
if (movingFlag) {
// 关闭弹窗
infoTip.close();
// 回到初始位置
marker.setPosition([116.478935, 39.997761]);
marker.stopMove();
// 清除已经移动的轨迹
passedPolyline.setPath([]);
movingFlag = false;
}
}
/*
监听移动事件:
点标记在执行moveTo,moveAlong动画时触发事件, e的格式是{passedPath:Array<LngLat>}
其中passedPath为Marker对象在moveAlong或者moveTo过程中已经走过的路径
*/
marker.on('moving', function (e) {
// setPath: 设置组成该折线的节点数组
passedPolyline.setPath(e.passedPath);
var length = e.passedPath.length;
// console.log(length, e.passedPath); 可以打印看看结构
// 在移动时更新信息
document.getElementById('tips').style.display = 'flex';
document.getElementById('license').innerText = '车牌号:' + data[length - 1].license;
document.getElementById('speed').innerText = '车速:' + data[length - 1].speed;
document.getElementById('longitude').innerText = '经度:' + data[length - 1].longitude;
document.getElementById('latitude').innerText = '纬度:' + data[length - 1].latitude;
document.getElementById('time').innerText = '时间:' + data[length - 1].time;
infoTip.open(map, marker.getPosition());
});
/*
setFitView(overlayList:Array/null, immediately:bool, avoid:[Number,Number,Number,Number], maxZoom:Number)
根据地图上添加的覆盖物分布情况,自动缩放地图到合适的视野级别,参数均可缺省
overlayList: 为覆盖物数组,缺省时为当前地图上添加的所有覆盖物图层
immediately: 代表是否需要动画过程
avoid: 代表上下左右的像素避让宽度
maxZoom: 代表fitView之后的最大级别
*/
map.setFitView();
</script>
- 样式文件
#container {
position: relative;
margin: 0 auto;
width: 800px;
height: calc(100vh - 50px);
}
#btn-card {
display: flex;
justify-content: space-evenly;
position: absolute;
bottom: 10px;
right: 10px;
align-items: center;
width: 280px;
height: 60px;
background-color: #fff;
background-clip: border-box;
box-shadow: 0 2px 6px 0 gray;
z-index: 999;
padding: 0 10px;
}
.operate {
font-size: 12px;
}
.btn {
padding: 2px 15px;
color: #25A5F7;
border: 1px solid #25A5F7;
background-color: transparent;
border-radius: 10px;
cursor: pointer;
}
.btn:hover {
color: #fff;
background-color: #25A5F7;
}
#tips {
height: 100px;
width: 180px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 5px;
background: #fff;
border: 1px solid #DEDEDD;
border-radius: 10px;
font-size: 12px;
display: none;
}