实际运行图(1):
实际运行图(2):
Html代码:
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<th:block th:include="include :: header('行驶轨迹')" />
<!--设置容器样式大小,使地图充满整个浏览器窗口:-->
<style type="text/css">
/*
html{height:100%}
body{height:100%;margin:0px;padding:0px}
#mapContainer{height:100%}
*/
</style>
<!-- 引用百度地图API文件 -->
<script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=你的密钥">
</script>
</head>
<body class="gray-bg">
<div class="container-div">
<div class="row">
<div class="col-sm-12 search-collapse">
<form id="formId">
<div class="select-list">
<ul>
<li class="select-time">
<label>行驶日期: </label>
<input type="text" class="time-input" id="startTime" placeholder="开始时间" name="params[beginTime]"/>
</li>
<li>
<a class="btn btn-primary btn-rounded btn-sm" onclick="searchTrack()"><i class="fa fa-search"></i> 搜索</a>
<a class="btn btn-warning btn-rounded btn-sm" onclick="resetTrack()"><i class="fa fa-refresh"></i> 重置</a>
</li>
</ul>
</div>
</form>
</div>
<div class="btn-group-sm" id="toolbar" role="group">
</div>
<div class="col-sm-12" style="margin-top: 15px; border: solid 1px #fff; border-radius: 6px; box-shadow: 1px 1px 3px rgba(0,0,0,.2);">
<div id="mapContainer" style="height:500px"></div>
</div>
</div>
</div>
<th:block th:include="include :: footer" />
</body>
</html>
JS代码:
完美实现了单次坐标转换同时绘制轨迹, 以合理的角度显示小车行驶图标(可以根据日期进行轨迹查询)
<script th:inline="javascript">
// GPS坐标
var GpsArr = [[${runTrack}]];
var GpsArrCp = GpsArr;
// console.info("GpsArr1");
// console.info(GpsArr);
var startTimeInit = [[${startTimeInit}]];
var endTimeInit = [[${endTimeInit}]];
var mid = [[${mid}]];
var map;
var convertor;
var carMk; // 小车的mark对象
var runningFlag = true; // false-画线运行中,true-画线运行结束
var interval;
$(function() {
$("#startTime").val(startTimeInit);
$("#endTime").val(endTimeInit);
map = new BMap.Map("mapContainer");
map.centerAndZoom(new BMap.Point(103.388611, 35.563611), 5); // 中国
map.enableScrollWheelZoom(); // 开启鼠标滚轮缩放
convertor = new BMap.Convertor();
justDoIt(GpsArr);
});
// 加入时间段逻辑
// 搜索
function searchTrack() {
// 如果有setInterval则取消
if (!runningFlag) { clearInterval(interval); }
var startTime = $("#startTime").val();
var endTime = $("#endTime").val();
// Request URL: http://localhost/clusters/bind/getRunTrack?mid=UWYZYYEU&start=2020-06-02&end=2020-06-02
$.get(ctx+"clusters/bind/getRunTrack?mid="+mid+"&start="+startTime+"&end="+endTime, function(res){
// console.info(res);
if (res.code == 0) {
GpsArr = res.data;
// console.info("GpsArr2");
// console.info(GpsArr);
map.clearOverlays(); // 清除地图上的覆盖物
map.reset(); // 重新设置地图,恢复地图初始化时的中心点和级别
justDoIt(GpsArr); // 展示行驶轨迹
} else {
alert("暂无数据");
}
});
}
// 重置
function resetTrack() {
if (!runningFlag) { clearInterval(interval); }
$("#startTime").val(startTimeInit);
map.clearOverlays(); // 清除地图上的覆盖物
map.reset(); // 重新设置地图,恢复地图初始化时的中心点和级别
justDoIt(GpsArrCp); // 展示行驶轨迹
}
translateCallback = function (data) {
// console.info(data);
if(data.status === 0) {
var bPointsArr = data.points;
if (bPointsArr.length != 0) {
var polyLineArr = [];
for (var i = 0 ; i < bPointsArr.length; i++) {
polyLineArr.push(new BMap.Point(bPointsArr[i].lng, bPointsArr[i].lat));
}
var polyline = new BMap.Polyline(polyLineArr, {strokeColor:"red", strokeWeight:7, strokeOpacity:1});
// 折线
map.addOverlay(polyline);
// 小车
littleCar(new BMap.Point(bPointsArr[1].lng, bPointsArr[1].lat), map, bPointsArr[1], new BMap.Point(bPointsArr[0].lng, bPointsArr[0].lat))
}
}
}
translateCallback2 = function (data) {
if(data.status === 0) {
var viewPoints = data.points;
addStartMarker(new BMap.Point(viewPoints[0].lng, viewPoints[0].lat), map);
var view = map.getViewport(viewPoints);
var zoom = view.zoom;
var centerPoint = view.center;
map.centerAndZoom(centerPoint, zoom);
}
}
translateCallback4 = function (data) {
if(data.status === 0) {
var polyLineArr = [];
var linePoints = data.points;
for (var i = 0 ; i < linePoints.length; i++) {
polyLineArr.push(new BMap.Point(linePoints[i].lng, linePoints[i].lat));
}
var polyline = new BMap.Polyline(polyLineArr, {strokeColor:"red", strokeWeight:7, strokeOpacity:1});
map.addOverlay(polyline);
}
}
// 确定最佳视野范围,同时显示起点图标
function getBestView(GpsArr) {
var startPoint = GpsArr[0];
var endPoint = GpsArr[GpsArr.length-1];
var viewPointArr = [];
var startViewPoint = new BMap.Point(startPoint.lng, startPoint.lat);
var endViewPoint = new BMap.Point(endPoint.lng, endPoint.lat);
viewPointArr.push(startViewPoint);
viewPointArr.push(endViewPoint);
// var convertor = new BMap.Convertor();
convertor.translate(viewPointArr, 1, 5, translateCallback2);
}
// 画轨迹
function drawTrack(GpsArr) { // GpsArr可用=371
runningFlag = false; // 画线运行中
var endNode = GpsArr.length % 2 == 0 ? GpsArr.length : GpsArr.length - 1 ; // 判断奇偶(是否能整除2)
var i = 0;
// 每200毫秒(0.2秒)执行1次 drowLine画线
interval = setInterval(function () {
if (i >= endNode) {
map.removeOverlay(carMk);
showEndMarker(GpsArr); // 显示终点图标
clearInterval(interval); // clearInterval()方法 可取消由setInterval() 设置的timeout
runningFlag = true; // 画线运行结束
return;
}
// 画线调用 (参数:坐标点1、坐标点2)
drowLine(GpsArr[i], GpsArr[i+1]);
i = i + 1;
// console.info("i="+i); // i=370
}, 100);
}
// 画线
function drowLine(gpsPointObj, gpsPointObjNext) {
var gpsPointArr = new BMap.Point(gpsPointObj.lng ,gpsPointObj.lat);
var gpsPointArrNext = new BMap.Point(gpsPointObjNext.lng ,gpsPointObjNext.lat);
var pointArr = [];
pointArr.push(gpsPointArr);
pointArr.push(gpsPointArrNext);
convertor.translate(pointArr, 1, 5, translateCallback);
}
// 添加起点图标
function addStartMarker(point, mapInit) {
var myIcon = new BMap.Icon("/img/startMap.png", new BMap.Size(45,45),{
anchor: new BMap.Size(20, 45),
imageSize:new BMap.Size(40, 45)
});
window.marker = new BMap.Marker(point,{icon:myIcon});
mapInit.addOverlay(marker);
}
translateCallback3 = function (data) {
if(data.status === 0) {
var viewPoints = data.points;
addEndMarker(new BMap.Point(viewPoints[0].lng, viewPoints[0].lat), map);
}
}
// 显示终点图标
function showEndMarker(GpsArr) {
var endPoint = GpsArr[GpsArr.length-1];
var endViewPoint = new BMap.Point(endPoint.lng, endPoint.lat);
var endViewPointArr = [];
endViewPointArr.push(endViewPoint);
convertor.translate(endViewPointArr, 1, 5, translateCallback3);
}
// 添加终点图标
function addEndMarker(point, mapInit) {
var myIcon = new BMap.Icon("/img/endMap.png", new BMap.Size(45,45),{
anchor: new BMap.Size(20, 45),
imageSize:new BMap.Size(40, 45)
});
window.marker = new BMap.Marker(point,{icon:myIcon});
mapInit.addOverlay(marker);
}
// 小车图标
var drivingPoint = new BMap.Icon('/img/carMap.png', new BMap.Size(50,24), {
anchor : new BMap.Size(27, 13),
imageSize:new BMap.Size(52,26)
});
// 小车行驶
function littleCar(point, mapInit, trackUnit, prePoint) {
// 先判断第一次进来的时候这个值有没有定义,有的话就清除掉上一次的。
// 然后在进行画图标。第一次进来时候没有定义也就不走这块,直接进行画图标
if(carMk){
mapInit.removeOverlay(carMk);
}
carMk = new BMap.Marker(point,{icon:drivingPoint}); // 创建标注
carMk.setRotation(trackUnit.route); // trackUnit.route
carMk.setRotation(getAngle(point,prePoint)+90); // 旋转的角度
mapInit.addOverlay(carMk); // 把标注添加到地图中
}
// 获得角度的方法
function getAngle(n, next){
var ret;
var w1 = n.lat/180 * Math.PI;
var j1 = n.lng/180 * Math.PI;
var w2 = next.lat/180 * Math.PI;
var j2 = next.lng/180 * Math.PI;
ret = 4 * Math.pow(Math.sin((w1 - w2) / 2), 2) - Math.pow(Math.sin((j1 - j2) / 2) * (Math.cos(w1) - Math.cos(w2)), 2);
ret = Math.sqrt(ret);
// var temp = Math.sin(Math.abs(j1 - j2) / 2) * (Math.cos(w1) + Math.cos(w2));
var temp = Math.sin((j1 - j2) / 2) * (Math.cos(w1) + Math.cos(w2));
// console.log(temp);
ret = ret/temp;
ret = Math.atan(ret) / Math.PI * 180 ;
ret += 90;
// 这里用如此臃肿的if..else是为了判定追踪单个点的具体情况,从而调整ret的值
if(j1-j2 < 0){
// console.log('j1<j2')
if(w1-w2 < 0){
// console.log('w1<w2')
ret;
}else{
// console.log('w1>w2')
ret = -ret+180;
}
}else{
// console.log('j1>j2')
if(w1-w2 < 0){
// console.log('w1<w2')
ret = 180+ret;
}else{
// console.log('w1>w2')
ret = -ret;
}
}
return ret ;
}
// 展示行驶轨迹
function justDoIt(GpsArr) {
if(GpsArr == undefined || GpsArr == null || GpsArr.length == 0) { alert("暂无数据"); return ;}
getBestView(GpsArr); // 视野范围,显示起点图标
drawTrack(GpsArr); // 转换坐标同时绘制行驶轨迹
}
</script>