记录基于geoserver地图服务,Openlayers3在web前端实现车辆轨迹回放功能,并记录和解决过程中出现的linestring只描绘部分经纬度坐标问题。
参考Openlayers3 官网例子
html
<!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初始化
$(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获取坐标数据
//轨迹查询按钮点击 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); }); });
显示轨迹
//轨迹描绘 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()); }
显示单点
//居中 车辆不运动时居中显示图标处理 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); }
点在线上运动,轨迹回放
//轨迹回放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坐标显示不全
期间碰到一个问题
var lineFeature = new ol.Feature({//路线 geometry: new ol.geom.LineString(positions,\'XY\'), }); linelayers.getSource().addFeature(lineFeature);
调用这段代码显示轨迹时,从数据库取到20个坐标,就可能只显示4个坐标,本来是弯曲的轨迹,但是实际上就是折线,很尴尬。
误打误撞,和同学 交流过程中发现问题所在,特此感谢。
在ajax获取坐标数据中发现问题所在:
原先错误代码
position = [data[i].lon,data[i].lat]; positions.push(position);
正确代码
position = [parseFloat(data[i].lon),parseFloat(data[i].lat)]; positions.push(position);
原因就是没有把float类型的坐标利用parseFloat强转,导致默认的泛数据类型精确度不够,经纬度小数点后末尾几位就会被忽略,于是造成数据失效,描出的线就会有问题。
附上icon、起点、终点、车辆等地图样式
//样式,供上述代码调用 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], })) });
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持免费资源网。
© 版权声明
THE END
暂无评论内容