First effect:
origin
When using the WeChat applet to do map-related functions, there is a requirement that you need to access the map service published by yourself. Check the WeChat applet map component document, found that it has very little map-related support, only some basic functions, such as adding points, lines, areas, bubbles and some regular map event monitoring, and does not add map service-related support .
But when there is a demand, we must find a way to solve it.
Layer query
Since the applet cannot directly add map services, find out the layer data and add it to the map by adding points, lines and polygons. How do you implement it?
The first thing that comes to mind is to find out all the data through the layer query interface.
But since the data is published by layer, the amount of data is generally relatively large. If you query all the data and add too much data to the map at one time, the map component will not be able to bear it and it will become stuck. In addition, the WeChat applet is single-time The data of setData()
1024kB
, so this scheme is not advisable.
Vector tiles
Since the amount of data requested at one time is too large, can it be requested in batches? So I thought of vector tiles.
Vector tiles are familiar to people who GIS
GIS
products to display large data maps.
But how do we make the small program map component that does not support adding external layers support vector tiles?
Checking the relevant documents of the map component, you will see that there is a regionchange
event, which is triggered when the view of the map changes, that is, when the map is dragged or zoomed. It will return the current center point, zoom level, map range and other information.
Get tiles
The next step is how to obtain vector tiles based on these parameters.
Suppose that the origin of the map cut is (originX,originY)
, the tile size of the tileSize
, and the actual distance represented by 1 pixel on the map screen is resolution
. The formula for calculating the row and column number of the tile where the coordinate point (x,y)
col = floor((x0 - x)/( tileSize*resolution))
row = floor((y0 - y)/( tileSize*resolution))
This formula should not be difficult to understand. To put it simply, first calculate the actual length LtileSize
LrealSize
between the geographic coordinate point on the screen and the starting point of the tile cut, and then Divide the actual distance by the actual length of a tile to get the tile row and column number at this time: LrealSize/LtileSize
.
The specific code is as follows:
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
}
},
Here you can see that there is a y value in the data I returned, and there is also a
tmsY
. This is becauseWMTS
andTMS
, the incoming y value is different, but there is a conversion between the two.tmsY = Math.pow(2, (level - 1)) - y - 1
, that is,WMTS
uses the y returned here, andTMS
uses thetmsY
returned here.Reference link:
Next, we only need to obtain the number of the tile that contains the current viewable area of the map according to the maximum and minimum coordinates of the current viewable area of the map and the map level.
Since the map component of the WeChat applet uses the encrypted coordinates of the National Bureau of Survey and Measurement, and the map service data I released is the wgs84
, the coordinate conversion method needs to be used to obtain the slice number to convert the coordinates of the National Bureau of Survey to wgs84
coordinates. For the method, please refer to leaflet how to elegantly solve the offset problem of Baidu and Gaode maps .
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)
}
}
},
Then pass in the request address and the x, y, and z parameters wx.request
geojson
format data corresponding to the vector slice
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)
}
})
},
Note that here I am usinggeoserver
. I found a problem during the call. In the data returned by one of the point layer tiles, each tile always has a lot of duplicate data. After inspection and testing, it is found that this is due to The style used when publishing this layer (point layer) is40x88
, which causes a lot of pixel values to be buffered outward when cutting the image. Therefore, ifgeoserver
publishes the layer It is used for vector slicing calls. It is best to set the point layer style to one pixel size pixel point, which can effectively reduce tile data redundancy
adding data
Finally, add points, lines and polygons to the map component of the WeChat applet to add the obtained slice data to the map.
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
})
},
There is a problem
At this point, the addition of vector tile data to the WeChat applet has been completed, which can basically meet the needs of browsing external vector layers, but there are still some shortcomings here.
- Need to publish
geojson
format vector tile layer - The layer will flash when the map is dragged. This is caused by the applet re-drawing the point, line and surface layer on the map
- When the small scale tile returns a large amount of data, there may be a stutter phenomenon (can be optimized by limiting the minimum scale)
- The layer map effect is limited by the point, line and surface style of the mini program map
Although this solution has some problems, it is still desirable in view of the limitations of the WeChat applet map component and the need to add layers in time.
Summarize
- The WeChat applet map component does not support adding external layer services
- By publishing the
geojson
format vector tile service, and then obtaining thegeojson
format tile data according to the current visible range regionchange
event of the applet map component to monitor the drag and zoom of the map, you can get the current center point, zoom level, and map range- According to the zoom level and map range, the tile number of the current visible range can be obtained
- Request tile data, add the tile data to the map by adding points, lines and planes to the map component of the WeChat applet
Code address
Code address: http://gisarmory.xyz/blog/index.html?source=WechatVectorTile
Original address: http://gisarmory.xyz/blog/index.html?blog=WechatVectorTile
Welcome to follow " GIS Weapons Library "
This article uses the Creative Commons Attribution-Non-Commercial Use-Same Method Sharing 4.0 International License Agreement for licensing. Welcome to reprint, use, and republish, but be sure to keep the article's signature "GIS Weapon Library" (including link: http://gisarmory.xyz/blog/ ), and it must not be used for commercial purposes. The same license is issued.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。