高仿ios相册地图功能

640?wx_fmt=png

今日科技快讯

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 相册, 地图算法分析。

高仿ios相册地图功能_第1张图片

下载.gif

正文

百度地图 SDK 新增点聚合功能。通过该功能,可通过缩小地图层级,将定义范围内的多个标注点,聚合显示成一个标注点,解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能。

基于百度地图优化算法流程:(其实百度也是抄袭 google map 的算法)

  1. 加入异步添加屏幕上图片

  2. 只加载屏幕范围内的图片

  3. 优化渲染逻辑,大大减少运算的时间
    (经过测试 2W 张不同经纬度的图片 300-500ms 可以计算完毕,绝对比 ios 相册还快。)

讲解点聚合功能,整个分析过程分为三个部分:

  1. 如何添加点聚合功能到项目中;

  2. 整体结构分析;

  3. 核心算法分析。

  • 添加聚合功能

如官网所示,添加点聚合的方法分为三步:声明点聚合管理类为全局变量,并初始化。核心代码如下图:

640?wx_fmt=jpeg

  • 整体结构分析

先上一个思维导图:

高仿ios相册地图功能_第2张图片

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

上图:

高仿ios相册地图功能_第3张图片

世界地图

高仿ios相册地图功能_第4张图片

墨卡托头影后的坐标轴

很明显墨卡托投影把整张世界地图投影成

X∈ [0,1] ; Y∈ [0,1]。

的一个正方型区域,世界宽度为 1 。
X 表示的是经度,Y表示的是纬度。
(其实准确来说是投影一个上下无限延伸的长方体,只是Y属于 [0,1] 这个范围已经足够我们使用)上图说明:

高仿ios相册地图功能_第5张图片

3.png

从上面看出  -85° 的纬度对应Y坐标是1,那么 -90° 呢,你们自己可以去算一下,是 +∞ (正无穷),90 ° 是 -∞ (负无穷) 。

至于为什么讲这个,因为计算搜索范围的时候,所有的经纬度都需要换算成Point 来计算,是不是很方便性,而且不易出错。
真是感叹伟人的强大!

  • 附注

转换的公式在下面这个类里面:

SphericalMercatorProjection.java

接下来说说如何通过四叉树组织数据

四叉树的基本思想是把空间递归划分为不同层次的树结构。它把已知的空间等分成四个相等的子空间,如此递归下去,直到满足当层数目量超过 50,或者层级数大于 40 则停止分割。示意图如下:

高仿ios相册地图功能_第6张图片

四叉树

OK,接下来说说具体流程

  • 遍历 QuadItem,只加载屏幕内的点,生成四叉树,方便搜索。

  • 如果图片已被 visitedCandidate 记录,则 continue 下面步骤,直到需要处理的图片没有被 visitedCandidates 记录;

  • 对上一次屏幕上的点QuadItem先进行处理;

  • 根据 MAX_DISTANCE_IN_DP 及图片位置计算出 searchBounds;

  • 通过四叉树得到 searchBounds 内所有的图片;

  • 如果图片数量为1,记录并跳到步骤2;

  • 遍历得到的图片;

  • 依次对得到的图片进行处理,

  • 如果图片到中心点的距离比 distanceToCluster (此图片与包含此图片的前cluster的距离)小,把图片加入结果集,并移除前 Cluster 拥有该图片的引用,并记录此次更小的距离,跳步骤 8 继续遍历剩余项。

重点源码分析:

  • 聚合触发口

ClusterManager.java

高仿ios相册地图功能_第7张图片

对地图进行手势操作,都会进行触发这个函数,并进行聚合操作

  • 算法运算

NonHierarchicalDistanceBasedAlgorithm.java

640?wx_fmt=jpeg

这个函数有点多,不过在 github 上面的 demo 已经注释满满,请移步 github 查看。

  • 渲染 UI(addMaker)

高仿ios相册地图功能_第8张图片

高仿ios相册地图功能_第9张图片

主要添加图片的是 onBeforeClusterRendered 这一个函数, 我们看一下实现:

高仿ios相册地图功能_第10张图片

很明显我这边解决了 baiduMap 在UI线程上添加图片阻塞问题, 添加强大的 fresco 第三方加载库,进行异步加载图片,接下来看图片下载完成后 执行setIconByCluster 函数:

高仿ios相册地图功能_第11张图片

总结

重点源码分析,基本上到这里结束。我们来撸一撸流程:

  • 通过 onMapStatusChangeFinish 回调,去执行点聚合运算;

  • 通过 getClusters 把聚合后的结果集算出来;

  • 通过CreateMarkerTask.perform() 把 marker 打到屏幕上。

备注

更多细节请看源代码
喜欢去帮忙start一下,谢谢!

github 地址:

https://github.com/zhangchaojiong/BaiduMapClusterSample/tree/master

更多

每天学习累了,看些搞笑的段子放松一下吧。关注最具娱乐精神的公众号,每天都有好心情。

640?wx_fmt=gif

如果你有好的技术文章想和大家分享,欢迎向我的公众号投稿,投稿具体细节请在公众号主页点击“投稿”菜单查看。

欢迎长按下图 -> 识别图中二维码或者扫一扫关注我的公众号:

640?wx_fmt=jpeg

你可能感兴趣的:(高仿ios相册地图功能)