一好友发过来了一个问题,她们的一个系统中,需要使用百度地图的路书功能来绘制整个飞机的航线以及动态过程,所以,就参考了百度地图中的一个Demo,
Demo地址:https://lbsyun.baidu.com/jsdemo.htm#webgl1_7
百度地图的集成使用,这里就不过多的说了,列一下主要的代码,
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 <script type="text/javascript" src="//api.map.baidu.com/api?type=webgl&v=1.0&ak=您的密钥" ></script> <script type ="text/javascript" src ="//api.map.baidu.com/library/LuShu/gl/src/LuShu_min.js" > </script > <div id ="allmap" > </div > var map = new BMapGL .Map ("allmap" );var point = new BMapGL .Point (116.404 , 39.925 );map.centerAndZoom (point, 4 ); map.enableScrollWheelZoom (); var path = [ new BMapGL .Point (116.617562 ,40.0823 ), new BMapGL .Point (37.700058 ,55.850864 ) ]; var polyline = new BMapGL .Polyline (path, { clip : false , geodesic : true , strokeWeight : 3 }); map.addOverlay (polyline); var fly = "小飞机图标" lushu = new BMapGLLib .LuShu (map, polyline.getPath (), { geodesic : true , autoCenter : true , icon : new BMapGL .Icon (fly, new BMapGL .Size (48 , 48 ), { anchor : new BMapGL .Size (24 , 24 ) }), speed : 1000000 , enableRotation : true }); lushu.start ()
接着直接看问题
官方的示例可以看到,设置好起始和终止坐标后,然后使用LuShu的相关api就可以展示行进的整个过程。 而她们希望是行进到其中的某个途经点时停止到这里。
她们查阅官方文档,并试验过的方法
BMapLib.LuShu
的类参考文档:http://api.map.baidu.com/library/LuShu/1.2/docs/symbols/BMapLib.LuShu.html
可以根据BMapLib.LuShu
的构造参数中的landmarkPois
来实现途经点的临时驻留。咱们就用官方的这个Demo的运行时
来做一些代码上的验证。
0x00 验证官方的landmarkPois功能
首先,咱们在官方的示例中添加一个途经点,比如,路过一下哈萨克斯坦吧:)
1 2 3 4 5 6 var path = [ new BMapGL .Point (116.617562 ,40.0823 ), new BMapGL .Point (70.273823 ,48.0273 ), new BMapGL .Point (37.700058 ,55.850864 ) ];
接着,配置landmarkPois
信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 lushu = new BMapGLLib .LuShu (map, polyline.getPath (), { geodesic : true , autoCenter : true , icon : new BMapGL .Icon (fly, new BMapGL .Size (48 , 48 ), { anchor : new BMapGL .Size (24 , 24 ) }), speed : 1000000 , enableRotation : true , landmarkPois : [{ lng : 70.273823 , lat : 48.0273 , html : '停止点' , pauseTime : 10 }] });
点击上方的【运行】则可以看到右侧的小飞机已经开始移动,并停留在我们设置的地标上,会停留10s后继续行进。
0x01 怎么让行进到地标后直接停止就不动了
按照程序的设计思维,停留时间参数的定义一般会是:
0 或者 null: 默认,表示不停留
正数:表示停留的时长
-1: 表示长时间驻留,不走了
由于javascript中,0和null在逻辑运算中都是false
,所以建议放一起,仅作为假设。
我们可以将landmarkPois
参数中的pauseTime: 10
修改为 pauseTime: 0
、pauseTime: -1
等各种情况来测试,发现都会不停留直接过去了,而官方文档中也没有明确的说明取值范围等。
背景交代完毕,哈哈哈哈,如果只是跟大家讨论百度地图怎么集成,那纯属浪费你们时间,随便搜索一下大把大把的资料。而我主要想说的就是,如果是你,作为开发人员,碰到这个问题该怎么做?
利用各种搜索引擎,变换关键词进行搜索,总有人做过相似的,抄还不会么。
找人询问,不行就各种技术群里、论坛发文章,总有人做过相似的,一说一听不爽么。
???
最近面试了不少的前端开发人员,可以说是跟着应聘者一起着急上火,感觉都是将一天重复了N年,咱不排斥混口饭,毕竟大家都是混口饭,但是,技术深度以及解决问题的能力是一个职业人应有的基本素养。会用几个框架组件又有什么用呢,碰到百度不到的问题就歇菜了么?实属不应该,说的有些偏题了,书归正文。
解决一个问题,就跟解答一到数学题是一样的,要先分析已知条件。
首先,我们要在脑中对BMapLib.LuShu的功能进行建模,比如,通过设置的landmarkPois
参数可以让行进到途经点后进行指定时间的驻留,那么,接着就是,分析一下这个驻留是如何实现的。
找到百度地图的路书源代码:http://api.map.baidu.com/library/LuShu/1.2/src/LuShu.js
短短代码,只有600来行,通过关键词搜索,可以找到这样一个函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 _troughPointIndex : function (markerPoi ) { var t = this ._opts .landmarkPois , distance; for (var i = 0 , len = t.length ; i < len; i++) { if (!t[i].bShow ) { distance = this ._map .getDistance (new BMap .Point (t[i].lng , t[i].lat ), markerPoi); if (distance < 10 ) { t[i].bShow = true ; return i; } } } return -1 ; }
查看 _troughPointIndex
函数的调用历史,或者搜索关键词,看在哪个逻辑中调用了这个函数来获取地标索引。可以找到这样一个函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 _setInfoWin : function (pos ) { var me = this ; if (!me._overlay ){ return ; } me._overlay .setPosition (pos, me._marker .getIcon ().size ); var index = me._troughPointIndex (pos); if (index != -1 ) { clearInterval (me._intervalFlag ); me._overlay .setHtml (me._opts .landmarkPois [index].html ); me._overlay .setPosition (pos, me._marker .getIcon ().size ); me._pauseForView (index); }else { me._overlay .setHtml (me._opts .defaultContent ); } },
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 _pauseForView : function (index ) { var me = this ; var t = setTimeout (function ( ) { me._moveNext (++me.i ); },me._opts .landmarkPois [index].pauseTime * 1000 ); me._setTimeoutQuene .push (t); },
也可以接着 _setInfoWin
函数向上跟踪,查看被调用链,是可以跟到 _move
函数的,这个是整个路书移动的核心函数,这里就不详细介绍了,我们主要是实现长时间停留。
通过_pauseForView
函数的逻辑,可以看出来,主要使用setTimeout
来做了个延时,由于时间计算并必填了,所以,我们设置0
、-1
也都不会生效。
那么,我们可以修改这里的代码逻辑,来实现一个pauseTime: -1
则进行长时间停留。
如何长时间停留呢?查看官方文档,可以看到有这样一个函数
如果pauseTime: -1
则调用pause()
来暂停住,就可以实现长时间驻留,反之,则继续走原有的逻辑。
思路和方法都有了,怎么实现呢?改源码再打包确实有些累,在js语言中,为什么会要求大家必须理解原型的概念,在这里,我们就可以利用原型的特性来完成函数的覆盖。
在官方的示例中,通过原型覆盖_pauseForView
函数,代码如下:
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 BMapGLLib .LuShu .prototype ._pauseForView = function (index ){ console .log ("到达经停点" ) var me = this ; const landmarkItem = me._opts .landmarkPois [index] const pauseTime = landmarkItem.pauseTime if (pauseTime == -1 ){ this .pause () }else { var t = setTimeout (function ( ) { me._moveNext (++me.i ); },pauseTime * 1000 ); me._setTimeoutQuene .push (t); } } lushu = new BMapGLLib .LuShu (map, polyline.getPath (), { geodesic : true , autoCenter : true , icon : new BMapGL .Icon (fly, new BMapGL .Size (48 , 48 ), { anchor : new BMapGL .Size (24 , 24 ) }), speed : 1000000 , enableRotation : true , landmarkPois : [{ lng : 70.273823 , lat : 48.0273 , html : '停止点' , pauseTime : -1 }] });
运行效果如图
代码只是示例验证代码,实际应用还得根据业务场景进行封装,这里之所以想说这个事儿,主要也是为你我做个警示,不要总是沉浸于会用多少框架,解决不了基础的问题,难免就会吐槽别人框架都是坑,而实际是自己没用好。