记录基于geoserver地图服务,Openlayers3在web前端实现车辆轨迹回放功能,并记录和解决过程中出现的linestring只描绘部分经纬度坐标问题。
参考Openlayers3 官网例子
html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
<!DOCTYPE html>
< html lang = "en" >
< head >
< title >车辆轨迹回放</ title >
< meta charset = "UTF-8" />
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" />
< link rel = "stylesheet" href = "../css/bootstrap.min.css" />
< link rel = "stylesheet" href = "../ol/ol.css" />
< style >
#map {
position: relative;
}
.popover{
min-width: 60px;
}
html{height:100%}
body{height:100%;margin:0px;padding:0px}
</ style >
</ head >
< body style = "margin: 0px 0px 0px 0px;line-height:0px;" >
< div id = "content" >
<!--<div id="map" style="height: 100%;width:100%"></div>-->
< div class = "row-fluid" >
< div >
< div id = "map" class = "map" ></ div >
</ div >
</ div >
< div class = "row-fluid" >
< div class = "span3" style = "position:absolute;top:0px;right:0px;" >
< div class = "accordion-group widget-box" >
< div class = "accordion-heading" >
< div class = "widget-title" >< a data-parent = "#collapse-group" href = "#collapseGOne"
data-toggle = "collapse" >< span class = "icon" >< i
class = "icon-map-marker" ></ i ></ span >
< h5 >轨迹查询</ h5 >
</ a >
</ div >
</ div >
< div class = "accordion-body in collapse" id = "collapseGOne" >
< div class = "form-actions" >
< div class = "control-group" style = "margin-bottom: 0px" >
< label class = "control-label" >< i class = "icon-truck" ></ i >设备</ label >
< div class = "controls" >
< select id = "busSelect" class = "span10" >
< option value = "*" >请选择设备</ option >
</ select >
</ div >
</ div >
</ div >
< div class = "form-actions" >
< div class = "control-group" style = "margin-bottom: 0px" >
< label class = "control-label" >< i class = "icon-table" ></ i >日期</ label >
< div class = "controls" >
< div data-date = "" class = "input-append date datepicker" >
< input id = "traceday" type = "text" data-date-format = "yyyy-mm-dd" class = "span10"
disabled>
< span class = "add-on" >< i class = "icon-time" ></ i ></ span ></ div >
</ div >
</ div >
</ div >
< div style = "padding: 19px 20px 20px; margin-top: 20px; margin-bottom: 20px;" >
< div class = "control-group" style = "margin-bottom: 0px" >
< button id = "queryBtn" class = "btn btn-primary" >< i class = "icon-search" ></ i > 轨迹查询</ button >
< span class = "remind" ></ span >
</ div >
< div class = "control-group" style = "margin-top: 10px" >
< button id = "animateBtn" class = "btn btn-info" >< i class = "icon-eye-open" ></ i > 轨迹回放</ button >
< input id = "speed" type = "range" min = "1" max = "100" step = "10" value = "10" > < span >< i class = "icon-cog" >速度</ i ></ span >
</ div >
</ div >
</ div >
</ div >
</ div >
</ div >
</ div >
</ div >
< script src = "../js/lib/jquery.min.js" ></ script >
< script src = "../js/lib/bootstrap.min.js" ></ script >
< script src = "../ol/ol-debug.js" ></ script >
< script src = "../ol/ol.js" ></ script >
< script src = "../js/globalVariable.js" ></ script >
< script src = "../js/gpsQueryAndroid.js" ></ script >
</ body >
</ html >
|
map初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
$(document).ready( function () {
map = new ol.Map({
logo: false ,
target: document.getElementById( 'map' ),
layers: layers,
view: view
});
initSelect(); //设备下拉框列表初始化
//时间控件初始化
$( '#s-traceday' ).val(transfromTime( new Date(), false )+ " 00:00:00" );
$( '#e-traceday' ).val(transfromTime( new Date(), true ));
$( '.datepicker' ).datetimepicker({
minView:0,
format: 'yyyy-MM-dd hh:mm:ss' ,
todayBtn : "linked" ,
autoclose : true ,
todayHighlight : true ,
startDate: daylimit,
endDate: '+1d' //结束时间,在这时间之后都不可选
});
});
//轨迹line layer
var vsource = new ol.source.Vector({
type: 'LineString' ,
features: []
});
var linelayers = new ol.layer.Vector({
source: vsource,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: '#0044CC'
}),
stroke: new ol.style.Stroke({
color: '#0044CC' ,
width: 4
})
})
});
//地图基础参数
var map;
var center = [121.6606763113213, 31.14611063632111];
var lng, lat;
var source = new ol.source.Vector({
wrapX: false
});;
var projection = new ol.proj.Projection({
code: 'EPSG:4326' ,
units: 'degrees' ,
axisOrientation: 'neu'
});
var view = new ol.View({
projection: projection,
center: center,
zoom: 16
});
var layers = [ new ol.layer.Tile({
title: '、地图' ,
visible: true ,
preload: Infinity,
source: new ol.source.TileWMS({
url: gisUrl,
params: {
'VERSION' : '1.1.0' ,
tiled: true ,
STYLES: '' ,
LAYERS: 'shanghai:maptest' ,
}
})
}),linelayers];
|
ajax获取坐标数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
//轨迹查询按钮点击
var positions=[];
$( "#queryBtn" ).click( function (){
//清除之前的图层
if (centerSource.getFeatures != null ) {
centerSource.clear(); }
linelayers.getSource().clear( true );
positions=[]; //清空
//取值
var busnum=$( "#busSelect" ).val();
var traceday=$( "#traceday" ).val();
if (busnum== "*" ){
$( ".remind" ).html( '<i class="icon-info-sign">请先选择车辆</i>' );
return ;
} else {
$( ".remind" ).html( '' );
busnum=busnum.slice(2);
}
if (transfromTime( new Date(), false )==traceday){ //当天
traceday= "*" ;
} else {
traceday=traceday.replace(/(-)/g, "" );
}
$( ".remind" ).html( '<i class="icon-cogs"> 正在查询...</i>' );
//请求
$.getJSON(baseUrl+ "trace/query/" +busnum+ "/" +traceday, "" , function (data){
if (data.length==0){
$( ".remind" ).html( '<i class="icon-info-sign">未查到gps数据</i>' ); return ;
}
var position = [];
for ( var i = 0;i<data.length;i++){
if (i!=0&&data[i].lon==data[i-1].lon&&data[i].lon==data[i-1].lon){ //去除重复数据
continue ;
}
position = [parseFloat(data[i].lon),parseFloat(data[i].lat)];
positions.push(position);
}
console.log(positions);
if (positions.length==1){
$( ".remind" ).html( '<i class="icon-info-sign">该车辆当天停在该位置未启动</i>' );
centerAt(positions[0]);
return ;
}
AddLayer(positions);
});
});
|
显示轨迹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
//轨迹描绘
function AddLayer() {
var lineFeature = new ol.Feature({ //路线
geometry: new ol.geom.LineString(positions, 'XY' ),
});
linelayers.getSource().addFeature(lineFeature);
var startFeature = new ol.Feature({ //起点
geometry: new ol.geom.Point(positions[0]),
population: 4000,
rainfall: 500
});
startFeature.setStyle(startStyle);
linelayers.getSource().addFeature(startFeature);
var endFeature = new ol.Feature({ //终点
geometry: new ol.geom.Point(positions[positions.length-1]),
population: 4000,
rainfall: 500
});
endFeature.setStyle(endStyle);
linelayers.getSource().addFeature(endFeature);
carFeature = new ol.Feature({ //车子
geometry: new ol.geom.Point(positions[0]),
population: 4000,
rainfall: 500
});
carFeature.setStyle(carStyle);
linelayers.getSource().addFeature(carFeature);
var extent = linelayers.getSource().getExtent(); //合适比例缩放居中
view.fit(extent, map.getSize());
}
|
显示单点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
//居中 车辆不运动时居中显示图标处理
var centerLayer = null ;
var centerSource = new ol.source.Vector({
features: null
});
//居中在一个位置
function centerAt(position) {
var pan = ol.animation.pan({
duration: 2000,
source: (view.getCenter())
});
view.setCenter(position);
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point(position),
name: 'Null Island' ,
population: 4000,
rainfall: 500
});
iconFeature.setStyle(iconStyle);
centerSource.addFeature(iconFeature);
centerLayer = new ol.layer.Vector({
source: centerSource
});
map.addLayer(centerLayer);
centerLayer.setVisible( true );
}
|
点在线上运动,轨迹回放
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
//轨迹回放start 参考官网
var carFeature = null ;
var speed, now;
var animating = false ;
$( "#animateBtn" ).click( function (){
if (positions.length==0){
$( ".remind" ).html( '<i class="icon-info-sign">请先查询轨迹</i>' );
return ;
}
if (animating) {
stopAnimation( false );
} else {
animating = true ;
now = new Date().getTime();
speed = $( "#speed" ).val(); //速度
$( "#animateBtn" ).html( '<i class="icon-eye-close"></i> 取消回放' );
carFeature.setStyle( null );
// map.getView().setCenter(center);
map.on( 'postcompose' , moveFeature);
map.render();
}
});
var moveFeature = function (event) {
var vectorContext = event.vectorContext;
var frameState = event.frameState;
if (animating) {
var elapsedTime = frameState.time - now;
// here the trick to increase speed is to jump some indexes
// on lineString coordinates
var index = Math.round(speed * elapsedTime / 1000);
if (index >= positions.length) {
stopAnimation( true );
return ;
}
var currentPoint = new ol.geom.Point(positions[index]);
var feature = new ol.Feature(currentPoint);
vectorContext.drawFeature(feature, carStyle);
}
// tell OL3 to continue the postcompose animation
map.render();
};
function startAnimation() {
if (animating) {
stopAnimation( false );
} else {
animating = true ;
now = new Date().getTime();
speed = speedInput.value;
$( "#animateBtn" ).html( '<i class="icon-eye-close"></i> 取消回放' );
// hide geoMarker
geoMarker.setStyle( null );
// just in case you pan somewhere else
map.getView().setCenter(center);
map.on( 'postcompose' , moveFeature);
map.render();
}
}
function stopAnimation(ended) {
animating = false ;
$( "#animateBtn" ).html( '<i class="icon-eye-open"></i> 轨迹回放' );
// if animation cancelled set the marker at the beginning
var coord = ended ? positions[positions.length - 1] : positions[0];
/** @type {ol.geom.Point} */ (carFeature.getGeometry())
.setCoordinates(coord);
//remove listener
map.un( 'postcompose' , moveFeature);
}
//轨迹回放end
|
解决linestring坐标显示不全
期间碰到一个问题
1
2
3
4
|
var lineFeature = new ol.Feature({ //路线
geometry: new ol.geom.LineString(positions, 'XY' ),
});
linelayers.getSource().addFeature(lineFeature);
|
调用这段代码显示轨迹时,从数据库取到20个坐标,就可能只显示4个坐标,本来是弯曲的轨迹,但是实际上就是折线,很尴尬。
误打误撞,和同学 交流过程中发现问题所在,特此感谢。
在ajax获取坐标数据中发现问题所在:
原先错误代码
1
2
|
position = [data[i].lon,data[i].lat];
positions.push(position);
|
正确代码
1
2
|
position = [parseFloat(data[i].lon),parseFloat(data[i].lat)];
positions.push(position);
|
原因就是没有把float类型的坐标利用parseFloat强转,导致默认的泛数据类型精确度不够,经纬度小数点后末尾几位就会被忽略,于是造成数据失效,描出的线就会有问题。
附上icon、起点、终点、车辆等地图样式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
//样式,供上述代码调用
var iconStyle = new ol.style.Style({
image: new ol.style.Icon( /** @type {olx.style.IconOptions} */ ({
anchor: [0.5, 0.8],
anchorXUnits: 'fraction' ,
anchorYUnits: 'pixels' ,
opacity: 0.75,
src: 'img/iconfont-weizhi-red.png'
}))
});
var startStyle = new ol.style.Style({
image: new ol.style.Icon( /** @type {olx.style.IconOptions} */ ({
anchor: [0.5, 0.8],
opacity: 0.8,
src: 'img/start.png'
/*anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
opacity: 0.75,*/
}))
});
var endStyle = new ol.style.Style({
image: new ol.style.Icon( /** @type {olx.style.IconOptions} */ ({
src: 'img/end.png' ,
anchor: [0.5, 0.8],
}))
});
var carStyle = new ol.style.Style({
image: new ol.style.Icon( /** @type {olx.style.IconOptions} */ ({
src: 'img/car.png' ,
anchor: [0.5, 0.8],
}))
});
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/u010543785/article/details/52486298