记录基于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