高仿ios相册地图功能
8月22日,据美国媒体报道,谷歌当日公布Android O系统的名称为Android Oreo(奥利奥)。此外,谷歌也将最新的源代码推送到Android开源项目(AOSP)。Android Oreo提供了一系列新功能,包括画中画、自动填写API、自动调节尺寸文本浏览、自适应图标、通知标志、高品质蓝牙音频解码和更严的应用安装控制。Android 8.0的亮点还包括重新设计的通知系统(包括视觉和功能方面的改进)、电池续航时间以及多屏幕支持等。而Oreo系统还将在启动启动速度和内存管理上都有很大提升,在Pixel手机上启动时间可以提升100%。另外,系统资源和后台任务管理的效率都有很大改善。
作者简介本篇来自 Override 的投稿,分享了一个高仿ios相册地图的功能,希望能对大家有所帮助。
Override 的博客地址:
前言http://www.jianshu.com/u/75711cf32043
老规矩先上图, 高仿 ios 相册, 地图算法分析。
下载.gif
正文百度地图 SDK 新增点聚合功能。通过该功能,可通过缩小地图层级,将定义范围内的多个标注点,聚合显示成一个标注点,解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能。
基于百度地图优化算法流程:(其实百度也是抄袭 google map 的算法)
加入异步添加屏幕上图片
只加载屏幕范围内的图片
优化渲染逻辑,大大减少运算的时间
(经过测试 2W 张不同经纬度的图片 300-500ms 可以计算完毕,绝对比 ios 相册还快。)
讲解点聚合功能,整个分析过程分为三个部分:
如何添加点聚合功能到项目中;
整体结构分析;
核心算法分析。
添加聚合功能
如官网所示,添加点聚合的方法分为三步:声明点聚合管理类为全局变量,并初始化。核心代码如下图:
整体结构分析
先上一个思维导图:
2.png
如上图,点聚合有四个类
Cluster 数据:主要是聚合数据类型,图示很明确,这里不罗嗦;
四叉树:记录初始范围内的所有图片并以四叉树的数据结构组织。核心算法需要用到的数据结构,后面再讲;
点聚合算法:基于四叉树的核心算法。后面讲;
Cluster 管理:对外接口,通过调用核心算法实现点聚合功能、
整个功能的主要流程有两条:
添加 item:Cluster 管理类添加 item 接口 算法类添加 item 接口:记录所有的图片信息 四叉树类添加 item 接口:已四叉树的结构记录所有图片信息
获取聚合后的集合:Cluster 管理类获取聚合接口 算法类核心算法接口:通过核心算法获取聚合后的集合
核心算法
首先要说一个概念:世界宽度。
百度地图是把整个地球是按照一个平面来展开,并且通过墨卡托投影投射到xy坐标轴上面。墨卡托投影链接地址:
https://zh.wikipedia.org/wiki/%E9%BA%A5%E5%8D%A1%E6%89%98%E6%8A%95%E5%BD%B1%E6%B3%95
上图:
世界地图
墨卡托头影后的坐标轴
很明显墨卡托投影把整张世界地图投影成
X∈ [0,1] ; Y∈ [0,1]。
的一个正方型区域,世界宽度为 1 。
X 表示的是经度,Y表示的是纬度。
(其实准确来说是投影一个上下无限延伸的长方体,只是Y属于 [0,1] 这个范围已经足够我们使用)上图说明:
3.png
从上面看出 -85° 的纬度对应Y坐标是1,那么 -90° 呢,你们自己可以去算一下,是 +∞ (正无穷),90 ° 是 -∞ (负无穷) 。
至于为什么讲这个,因为计算搜索范围的时候,所有的经纬度都需要换算成Point 来计算,是不是很方便性,而且不易出错。
真是感叹伟人的强大!
附注
转换的公式在下面这个类里面:
SphericalMercatorProjection.java
接下来说说如何通过四叉树组织数据
四叉树的基本思想是把空间递归划分为不同层次的树结构。它把已知的空间等分成四个相等的子空间,如此递归下去,直到满足当层数目量超过 50,或者层级数大于 40 则停止分割。示意图如下:
四叉树
OK,接下来说说具体流程
遍历 QuadItem,只加载屏幕内的点,生成四叉树,方便搜索。
如果图片已被 visitedCandidate 记录,则 continue 下面步骤,直到需要处理的图片没有被 visitedCandidates 记录;
对上一次屏幕上的点QuadItem先进行处理;
根据 MAX_DISTANCE_IN_DP 及图片位置计算出 searchBounds;
通过四叉树得到 searchBounds 内所有的图片;
如果图片数量为1,记录并跳到步骤2;
遍历得到的图片;
依次对得到的图片进行处理,
如果图片到中心点的距离比 distanceToCluster (此图片与包含此图片的前cluster的距离)小,把图片加入结果集,并移除前 Cluster 拥有该图片的引用,并记录此次更小的距离,跳步骤 8 继续遍历剩余项。
重点源码分析:
聚合触发口
ClusterManager.java
对地图进行手势操作,都会进行触发这个函数,并进行聚合操作
算法运算
NonHierarchicalDistanceBasedAlgorithm.java
这个函数有点多,不过在 github 上面的 demo 已经注释满满,请移步 github 查看。
渲染 UI(addMaker)
主要添加图片的是 onBeforeClusterRendered 这一个函数, 我们看一下实现:
很明显我这边解决了 baiduMap 在UI线程上添加图片阻塞问题, 添加强大的 fresco 第三方加载库,进行异步加载图片,接下来看图片下载完成后 执行setIconByCluster 函数:
重点源码分析,基本上到这里结束。我们来撸一撸流程:
通过 onMapStatusChangeFinish 回调,去执行点聚合运算;
通过 getClusters 把聚合后的结果集算出来;
通过CreateMarkerTask.perform() 把 marker 打到屏幕上。
更多细节请看源代码
喜欢去帮忙start一下,谢谢!
github 地址:
更多https://github.com/zhangchaojiong/BaiduMapClusterSample/tree/master
每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。
如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。
欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号: