本文主要是介绍基于Openlayers3的地图轨迹及其优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、背景
项目线上系统经常出现一个问题,当地图轨迹点较多后者出现跨度较大的跳跃点时,地图缩放轨迹计算会导致浏览器比较卡,非常影响用户体验,根本原因是因为地图轨迹在进行缩放时,会在前端重新计算轨迹箭头图层的位置信息,当看到计算入口代码时,发现计算比较暴力,计算时间复杂度太高,需要进行优化,通过网上查询,发现一个博主的做法能有效降低计算的时间复杂度(https://blog.csdn.net/freeland1/article/details/82113809),但实践后发现其存在一个问题,当存在两个点间来回的轨迹时,其做法只能显示一个方向的箭头,没有展示反向的箭头。
二、轨迹绘制及优化
组件 | 地址 |
---|---|
openlayers | https://openlayers.org/ |
rbush | https://unpkg.com/rbush@2.0.1/rbush.min.js |
注意:openlayers版本需v3.13.0及以上,低版本不支持不支持getCoordinateAt方法
附地图缩放时,轨迹箭头更新逻辑代码:
/***地图缩放时,更新轨迹箭头*/updateTrackArrowStyle: function (geometry, lineWidth, lineColor, arrowIcon) {var _this = this;var trackLine = geometry;var zoom = window.map.getView().getZoom();var distance = 57*(19-zoom)*(19-zoom);//箭头间隔随地图层级变化var styles = [new ol.style.Style({stroke: new ol.style.Stroke({color: lineColor,width: lineWidth})})];var length = _this.getLineLength(trackLine);if(length < 2 * distance){if(length < distance){distance = length / 3;}else{distance = length / 4;}}//对segments建立btree索引var tree = rbush();//路段数var max_num = 1;var geomLength = 0;trackLine.forEachSegment(function(start, end) {var dx = end[0] - start[0];var dy = end[1] - start[1];var rotation = Math.atan2(dy, dx);var geom = new ol.geom.LineString([start,end]);var extent = geom.getExtent();geomLength += _this.getLineLength(geom);var min_num = max_num;max_num = parseInt(geomLength / distance);//计算每一段轨迹上箭头在整段轨迹中的索引var item = {minX: extent[0],minY: extent[1],maxX: extent[2],maxY: extent[3],geom: geom,min_num: min_num,max_num: max_num,rotation_o : null,rotation_n : null,rotation: rotation};tree.insert(item);});var recExtent = map.getView().calculateExtent(map.getSize());//箭头总数var arrowsNum = parseInt(length / distance);var isRepeat = true;for(var i = 1;i < arrowsNum;i++){var arrowIcon = arrowIcon;var arraw_coor = trackLine.getCoordinateAt(i*1.0/arrowsNum);var tol = 0.1;var arraw_coor_buffer = [arraw_coor[0]-tol,arraw_coor[1]-tol,arraw_coor[0]+tol,arraw_coor[1]+tol];//进行btree查询var treeSearch = tree.search({minX: arraw_coor_buffer[0],minY: arraw_coor_buffer[1],maxX: arraw_coor_buffer[2],maxY: arraw_coor_buffer[3]});var arrow_rotation;if(treeSearch.length == 1){isRepeat = true;arrow_rotation = treeSearch[0].rotation;}else if(treeSearch.length > 1){var results = treeSearch.filter(function(item){var _tol = 0.1;//消除精度误差的容差if(item.geom.intersectsExtent([arraw_coor[0]-_tol, arraw_coor[1]-_tol, arraw_coor[0]+_tol, arraw_coor[1]+_tol]))return true;})if(results.length > 0){for(var j = 0;j < results.length;j++){if(i >= results[j].min_num && i <= results[j].max_num){//判断箭头是否在该段轨迹上if(i == results[j].min_num + 1){if(!results[j].rotation_o){isRepeat = true;for(var k=0;k<results.length;k++){results[k].rotation_o = results[j].rotation;}}else if(results[j].rotation_o == results[j].rotation){isRepeat = false;}else if(!results[j].rotation_n){isRepeat = true;for(var k=0;k<results.length;k++){results[k].rotation_n = results[j].rotation;}}else if(results[j].rotation_n == results[j].rotation){isRepeat = false;}}arrow_rotation = results[j].rotation;break;}}}}if(isRepeat){//判断是否已显示,当轨迹来回次数比较多时,如果不去冲,会在轨迹上堆积很多箭头styles.push(new ol.style.Style({geometry: new ol.geom.Point(arraw_coor),image: new ol.style.Icon({src: arrowIcon,anchor: [0.75, 0.5],rotateWithView: false,rotation: -arrow_rotation})}));}}return styles;},/***计算轨迹长度*/getLineLength : function(line){var coordinates = line.getCoordinates();var length = 0;var sourceProj = map.getView().getProjection();for (var i = 0, ii = coordinates.length - 1; i < ii; ++i) {var c1 = ol.proj.transform(coordinates[i], sourceProj, 'EPSG:4326');var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'EPSG:4326');length += new ol.Sphere(6378137).haversineDistance(c1, c2);}return (Math.round(length * 100) / 100);}
三、效果图
1、无来回点
2、有来回点
如果您有好的改进建议,还请留言,不吝赐教!
这篇关于基于Openlayers3的地图轨迹及其优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!