共计 4266 个字符,预计需要花费 11 分钟才能阅读完成。
先上成果:
缘起
应用微信小程序做地图相干性能的时候,有个需要是须要接入本人公布的地图服务。查看微信小程序地图组件文档,发现它对地图相干的反对很少,只有一些根底性能,比方增加点、线、面、气泡和一些惯例的地图事件监听,并没有增加地图服务相干的反对。
不过有了需要,也要想方法解决呀。
图层查问
既然小程序不能间接增加地图服务,那就把图层数据查出来,而后通过增加点线面形式增加到地图,具体要怎么实现呢?
首先想到的是通过图层查问接口把所有数据查出来。
然而既然数据是按图层公布的,个别数据量都比拟大,把所有数据查问进去,一次性增加过多的数据到地图,地图组件会受不了从而变的卡顿,另外微信小程序单次 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, 0.0006866455078125, 0.0003433227539062,
0.0001716613769531, 0.0000858306884766, 0.0000429153442383, 0.0000214576721191, 0.0000107288360596,
0.0000053644180298, 0.0000026822090149, 0.0000013411045074, 0.0000006705522537, 0.0000003352761269
]
let tileSize = 256 // 这个值示意的是每张切片的大小, 个别都是 256
let coef = resolution[level] * tileSize;
let x = Math.floor((lon - originX) / coef); // 向下取整, 抛弃小数局部
let y = Math.floor((originY - lat) / coef); // 向下取整, 抛弃小数局部
let tmsY = Math.pow(2, (level - 1)) - y - 1;
return {
x: x,
y: y,
z: level - 1,
tmsY: tmsY
}
},
这里能够看到我返回的数据中有一个 y 值,还有一个
tmsY
,这是因为WMTS
、TMS
两种形式调用切片时,传入的 y 值是不同的,不过两者之间是有能够转换的,也就是tmsY = Math.pow(2, (level - 1)) - y - 1
,WMTS
用的是这里返回的 y,TMS
用的是这里返回 的tmsY
。参考链接:
WebGIS 前端地图显示之依据天文范畴换算出瓦片行列号的原理(外围)
Slippy_map_tilenames
TMS 和 WMTS 大略比照
接下来咱们只需依据以后地图可视范畴的最大、最小坐标以及地图层级,即可获取蕴含以后地图可视范畴的瓦片的编号。
因为微信小程序地图组件应用的是国测局加密坐标,而我公布的地图服务数据为 wgs84
坐标,因而这里在获取切片编号时须要用坐标转换方法将国测局坐标转成 wgs84
坐标,坐标纠偏办法可参考 leaflet 中如何优雅的解决百度、高德地图的偏移问题。
getXYZList: function (region, level) {
// 坐标转换
var newsouthwest = appcoord.gcj02_To_gps84(region.southwest.longitude, region.southwest.latitude);
var northeastwest = appcoord.gcj02_To_gps84(region.northeast.longitude, region.northeast.latitude);
// 获取瓦片编号
var xyzInfo1 = this.getTileXY(newsouthwest.lng, northeastwest.lat, level)
var xyzInfo2 = this.getTileXY(northeastwest.lng, newsouthwest.lat, level)
var z = level - 1
for (var x = xyzInfo1.x; x <= xyzInfo2.x; x++) {for (var y = xyzInfo1.y; y <= xyzInfo2.y; y++) {this.getGeoJson(x, y, z)
}
}
},
而后通过 wx.request
传入申请地址以及 x、y、z 参数,即可获取到对应矢量切片的 geojson
格局数据
getGeoJson: function (x, y, z) {
const v = this
wx.request({
url: "http://127.0.0.1:7000/geoserver/gwc/service/wmts/rest/test:test/EPSG:4326/EPSG:4326:" +
z + "/" + y + "/" + x + "?format=application/json;type=geojson",
method: 'get',
success(res) {
var tileId = 'tile-' + x + '-' + y + '-' + z
tileData[tileId] = {
tileId: tileId,
features: []}
if(res.statusCode === 200){tileData[tileId].features = res.data.features
}
v.addFeatures(tileId)
}
})
},
留神,这里我是用
geoserver
公布的矢量瓦片,在调用过程中发现个问题,其中一个点图层瓦片返回的数据中,各个瓦片总有很多反复数据,经查看测试发现,这是因为公布该图层(点图层)时应用的款式为一张大小为40x88
的图片点样,这就导致切图时整体向外缓冲了不少的像素值,所以,如果geoserver
公布的图层是用于矢量切片调用,最好将点图层款式设置为一个像素大小的像素点,这样能够无效缩小瓦片数据冗余
增加数据
最初再通过微信小程序地图组件中增加点线面的办法把获取切片数据增加到地图即可
addFeatures: function (tileId) {
var polylines = this.data.polylines
var markers = this.data.markers
tileData[tileId].features.forEach(feature => {if (feature.geometry.type === 'LineString') {polylines.push(this.getPolyline(feature.geometry.coordinates, tileId))
} else if (feature.geometry.type === 'Point') {markers.push(this.getMarker(feature.geometry.coordinates, tileId))
}
});
this.setData({
polylines: polylines,
markers: markers
})
},
存在问题
至此,微信小程序增加矢量瓦片数据曾经实现,根本能满足浏览内部矢量图层的需要,然而,这里还是有一些有余的中央
- 须要公布
geojson
格局矢量瓦片图层 - 地图拖动时图层会闪一下,这是小程序从新往地图上绘制点线面图层引起的
- 在小比例尺瓦片返回数据量较大时可能会有卡顿景象(能够通过限定最小比例尺优化)
- 图层配图成果受小程序地图点线面款式限度
尽管该解决方案存在一些问题,然而鉴于微信小程序地图组件的限度,并且确时又有增加图层的需要,此计划还是可取的。
总结
- 微信小程序地图组件不反对增加内部图层服务
- 通过公布
geojson
格局矢量瓦片服务,而后按以后可视范畴获取geojson
格局瓦片数据 - 通过小程序地图组件的
regionchange
事件监听地图拖动、缩放,能够获取到以后中心点、缩放级别、地图范畴 - 依据缩放级别、地图范畴能够获取到以后可视范畴的瓦片编号
- 申请瓦片数据,通过微信小程序地图组件中增加点线面的办法把切片数据增加到地图
代码地址
代码地址:http://gisarmory.xyz/blog/index.html?source=WechatVectorTile
原文地址:http://gisarmory.xyz/blog/index.html?blog=WechatVectorTile
欢送关注《GIS 兵器库》
本文章采纳 常识共享署名 - 非商业性应用 - 雷同形式共享 4.0 国内许可协定 进行许可。欢送转载、应用、从新公布,但务必保留文章署名《GIS 兵器库》(蕴含链接:http://gisarmory.xyz/blog/),不得用于商业目标,基于本文批改后的作品务必以雷同的许可公布。