客户端中涉及到了mapView坐标系的转化,有必要在这里先做一下记录。众所周知地球是一个不规则椭圆体,GIS中的坐标系定义由基准面和地图投影两组参数确定,而基准面的定义则由特定椭球体及其对应的转换参数确定。 基准面是利用特定椭球体对特定地区地球表面的逼近,因此每个国家或地区均有各自的基准面。基准面是在椭球体基础上建立的,椭球体可以对应多个基准面,而基准面只能对应一个椭球体。意思就是无论是谷歌地图、搜搜地图还是高德地图、百度地图区别只是针对不同的大地地理坐标系标准制作的经纬度,不存在准不准的问题,大家都是准的只是参照物或者说是标准不一样。谷歌地图采用的是WGS84地理坐标系(中国范围除外),谷歌中国地图和搜搜中国地图采用的是GCJ02地理坐标系,百度采用的是BD09坐标系,而设备一般包含GPS芯片或者北斗芯片获取的经纬度为WGS84地理坐标系,为什么不统一用WGS84地理坐标系这就是国家地理测绘总局对于出版地图的要求,出版地图必须符合GCJ02坐标系标准了,也就是国家规定不能直接使用WGS84地理坐标系。所以定位大家感觉不准确很多又叫出版地图为火星地图其实只是坐标系不一样而已。这就是为什么设备采集的经纬度在地图上显示的时候经常有很大的偏差,远远超出民用GPS 10米偏移量的技术规范。
以上参考自:haotsp.com
总结:
- WGS84坐标系:即地球坐标系,国际上通用的坐标系。
- GCJ02坐标系:即火星坐标系,WGS84坐标系经加密后的坐标系。
- BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系。
- 搜狗坐标系、图吧坐标系等,估计也是在GCJ02基础上加密而成的。
下面是不同的api使用的坐标系的情况:
- 百度地图API 百度坐标
- 腾讯搜搜地图API 火星坐标
- 搜狐搜狗地图API 搜狗坐标*
- 阿里云地图API 火星坐标
- 图吧MapBar地图API 图吧坐标
- 高德MapABC地图API 火星坐标
- 灵图51ditu地图API 火星坐标
Apple中存在的现状
在ios API中可以从两个不同的API来获取坐标:
- CoreLocation。这个坐标系一般采用的都是当前国家的基准,在我国范围的坐标使用的就是GCJ02坐标系
- MapKit。这个坐标系从当前的测试来看,采用的基准是WGS84
这里存在一个大前提,我们希望使用MapKit自带的showCurrentLocation,就是地图中会显示当前坐标的一个蓝色的点(这个蓝色的点存在脉冲动画),同时我们希望用CoreLocation采集到的目标经纬度和这个当前的点做连线。但是存在一些问题:
- 在RN中无法在不更改reactNative代码的情况下拿到MapKit中当前的经纬度。
- 服务器返回的经纬度可能没有做校准(没有将GCJ02->WGS84)
这里做的就是做经纬度的坐标系的转化,但是这种转化还是存在误差,只是误差范围比较小
此次地图改动的地方
此次rn改版中目的是使用facebook中的源码来完成业务的开发,此处源码是保持和facebook同源的状态,业务自定义界面通过拓展的方式完成。这样一来之前的mapView的实现就需要做很大的调整,这里先介绍一下之前的实现
RCTMapManager中的改动
- AnnotationView中的地址复用
- 32bit设备上异步资源获取
- mapView中中心点
- 路径加载
上面的这些问题在该版本之前都是在facebook的源码中加上的,所以每次升级都需要再次测试的工作。在此次升级的推动下,将上面的问题全部抽出来以便保证源码的纯净
策略:
- 增加AnnotationView中的key来避免地址复用
- runtime swizzling实现延时调用
- category 增加方法
- 抽出数据,利用overlays实现路径的加载
存在的问题
在以前的32bit的机器上存在这样的问题,JS线程和系统的线程异步的情况,导致了native的代码先执行,没有拿到相关View的对象,在界面上显示的就不在是对应类型的图片,而是一个大头针。有两种方法来做相关的事情
- 抛弃32bit设备的优化。这里并不会出现bug,只是没有拿到View对象,所以在界面上显示的是大头针
- 在mapView中增加拓展的对象。在这个拓展的对象中做延时处理,有一定的时间间隙来完成View对象的加载,这个时间在0.1秒就可以获取到对象。 但是这里还是需要mapView.js完成新的property的解析
这里是通过runtime swizz这个方法来实现延时加载的这个过程