先上效果:
缘起
使用微信小程序做地图相关功能的时候,有个需求是需要接入自己发布的地图服务。查看微信小程序地图组件文档,发现它对地图相关的支持很少,只有一些基础功能,比如添加点、线、面、气泡和一些常规的地图事件监听,并没有添加地图服务相关的支持。
不过有了需求,也要想办法解决呀。
图层查询
既然小程序不能直接添加地图服务,那就把图层数据查出来,然后通过添加点线面方式添加到地图,具体要怎么实现呢?
首先想到的是通过图层查询接口把所有数据查出来。
但是既然数据是按图层发布的,一般数据量都比较大,把所有数据查询出来,一次性添加过多的数据到地图,地图组件会受不了从而变的卡顿,另外微信小程序单次setData()
的数据不能超过1024kB
,因此这种方案就不可取了。
矢量瓦片
既然一次性请求数据量太大,是不是可以分批次请求呢?于是就想到了矢量瓦片。
矢量瓦片对于做GIS
的人来说,大家都很熟悉了,这也是目前各种GIS
产品对大数据量地图展示所采用的主要方式。
但是,我们如何让不支持添加外部图层的小程序地图组件支持矢量瓦片呢?
查看地图组件相关文档,会看到其中有个regionchange
事件,该事件是在地图视野改变,也就是拖动、缩放地图时触发,它会返回当前中心点、缩放级别、地图范围等信息。
获取瓦片
接下来就是如何根据这些参数获取到矢量瓦片了。
假设,地图切图的原点是(originX,originY)
,地图的瓦片大小是tileSize
,地图屏幕上1像素代表的实际距离是resolution
。计算坐标点(x,y)
所在的瓦片的行列号的公式是:
col = floor((x0 - x)/( tileSize*resolution))
row = floor((y0 - y)/( tileSize*resolution))
这个公式应该不难理解,简单点说就是,先算出一个瓦片所包含的实际长度LtileSize
,然后再算出此时屏幕上的地理坐标点离瓦片切图的起始点间的实际距离LrealSize
,然后用实际距离除以一个瓦片的实际长度,即可得此时的瓦片行列号:LrealSize/LtileSize
。
具体代码如下:
getTileXY: function (lon, lat, level) {
let originX = -180; //坐标系原点的x的值,
let originY = 90; //坐标系原点的y的值
//根据你自己对应的切片方案改,这个就是其分辨率resolution
let resolution = [1.40625, 0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625,
0.010986328125, 0.0054931640625, 0.00274658203125, 0.001373291015625