一 前言

近期翻阅博客,看到社区大神一休哥的一篇《canvas 奇巧淫技(二)绘制箭头路径效果》文章,同样,该大神还展示过一个使用rbush库如何在前端快速从海量数据进行空间检索的案例:https://alex2wong.github.io/mapbox-plugins/examples/rbush/,很有分享精神的前端GIS专家,更多关于前端GIS检索数据的技术可参考搜狐的干货专访:《深入理解空间搜索算法 ——数百万数据中的瞬时搜索》。关于轨迹样式带导航箭头这种常见问题,笔者基于兴趣和朋友们的总结,也试着用熟悉的OpenLayers的StyleFunction去实现一个这样的玩具,在此分享给大家。


高德轨迹箭头.png

基于已知的一条轨迹,实现这样的一个导航轨迹箭头,需要解决三个问题:

在轨迹上根据固定像素间隔,计算当前地图分辨率下箭头总数量。

计算当前地图分辨率下,每个箭头的绘制位置。

计算好箭头的数量和位置后,要确定箭头的方向。

一 箭头数量

由高德轨迹箭头图可知,每隔固定像素,打上一个箭头。假设当前的线LineString地理长度为length,当前固定像素间隔stpes=n像素,在当前地图比例尺res已知的情况下,n像素地理距离是resn,那么箭头总数count=length/(resn):

多么浅显易懂的道理啊,第一个问题很顺利的解决了。

二 箭头位置

第一步得到了箭头的总数,在获取箭头位置时,一个重要的API是线条LineString的getCoordinateAt,利用它我们在轨迹线上获取箭头点的位置。

假如箭头总数为arrowsNum,那么arrowsNum个箭头的数量分别是

得到每个箭头的位置后,我们先可视化下吧,OpenLayers的地图样式完全由StyleFunction实现的,完整样式代码如下:


箭头位置计算与可视化结果.png

三 箭头方向

之前的逻辑,我们已经计算了一个轨迹样式的雏形了,把地图上箭头位置的黄点改成一个箭头图标,做下方向旋转就可以了。在说明此前,需要说明下轨迹,segment线段,箭头点之间的关系,如下图:


轨迹,segment,箭头位置之间的关系.png

观察示意图,总结如下:

一条完整的轨迹由多个连续的segment组成。

通过getCoordinateAt方法计算得到的箭头点,一定是在轨迹线上的某个点。

每个箭头点的方向是由箭头点落在的segment的方向决定的。

很显然,计算箭头方向其实就是计算每个箭头点到底落在了哪个segment上,将segme方向赋予箭头点。这里我们引入了rbush库构建空间索引,计算轨迹点与segment对应关系。

之所以我要引入rbush库,是解决循环计算问题,想象下如果不引入rbush库,只能使用如下的伪代码暴力计算了:

感觉逻辑很简单啊,这样做难道不可以吗?想象下,箭头数量,segment的数量其实都是不可控的,一个复杂的轨迹线可能由成百上千的近万的segments,这样一个个循环去匹配,效率是不是就有问题了?所以引入了空间索引。这里查询,使用了rbush进行btree查询,查询的结果后再详细比对是否和箭头相交,累了,直接贴代码了,不详述了:


轨迹箭头效果图.png

看着还凑合吧,但其实要做到高德那个精细的样式,才万里第一步,祝诸君继续研究,期待更好的效果。