Openlayers3实现车辆轨迹回放功能

记录基于geoserver地图服务,Openlayers3在web前端实现车辆轨迹回放功能,并记录和解决过程中出现的linestring只描绘部分经纬度坐标问题。

参考Openlayers3 官网例子

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>&nbsp;轨迹查询</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>&nbsp;轨迹回放</button> 
  <input id=\"speed\" type=\"range\" min=\"1\" max=\"100\" step=\"10\" value=\"10\">&nbsp;<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>&nbsp;取消回放\');
 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>&nbsp;取消回放\');
 // 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>&nbsp;轨迹回放\');

 // 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
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容