1、问题现象
使用leaflet显示矢量瓦片会出现图片挤压的问题和图片裁剪显示不全的问题
2、解决办法和思路
1)数据抽稀
方法一:在createTile方法通过控制feature在单张瓦片里面显示的数量,在小层级的时候进行筛选过滤,对点数据类型,代码如下:
//判断当期瓦片里面的features,然后对数据进行抽稀,显示的数量不超过5个
//小于14层的瓦片,抽稀,显示的数量不超过5个,大于14级全部显示
if (
(coords.z <= 14 && layer.features.length > 5 && feat.id % Math.ceil(layer.features.length / 5) == 0) ||
layer.features.length <= 5 ||
coords.z > 14 ||
feat.type != 1
) {
var featureLayer = this._createLayer(feat, pxPerExtent)
for (var j = 0; j < styleOptions.length; j++) {
var style = L.extend({}, L.Path.prototype.options, styleOptions[j])
featureLayer.render(renderer, style)
renderer._addPath(featureLayer)
}
if (this.options.interactive) {
featureLayer.makeInteractive()
}
if (storeFeatures) {
renderer._features[id] = {
layerName: layerName,
feature: featureLayer
}
}
}
方法二:通过设置矢量瓦片vectorTileLayerStyles的样式,可以获取到当前的层级和数据信息,设置一个空的占位图标解决抽稀问题:
vectorTileLayerStyles[layerStyle.layername] = function (properties: any, zoom: number) {
if (options && options.length > 0) {
let style = {} //返回的数据格式
options.forEach((item: any) => {
//如何当前的层级落在option的zoom数组范围内
if (zoom >= item.zoom[0] && zoom <= item.zoom[1]) {
let icon = L.icon({
iconUrl: `/static/images/Iconpoint/${item.iconName}.svg`,
iconSize: item.iconSize
})
//点的数据抽稀设置
if (item.sliceCount && item.fieldname) {
let data = properties[item.fieldname]
//测试用
// data = data.split('.')[1]
//取余数
if (data && Number(data) % Number(item.sliceCount) == 0) {
style = {
icon: icon
}
} else {
style = {
icon: defaultIcon
}
}
}
}
})
return style
options配置如下:
options: [
{
zoom: [1, 10], //不同层级下的显示最小值和最大值
sliceCount: 70, //抽稀的数量
iconSize: [23, 30],
iconName: 'monitorvideo',
fieldname: 'gbindexcode'//抽稀属性字段
},
{
zoom: [11, 12], //不同层级下的显示
sliceCount: 20, //抽稀的数量
iconSize: [23, 30],
iconName: 'monitorvideo',
fieldname: 'gbindexcode'
},
{
zoom: [13, 15], //不同层级下的显示
sliceCount: 10, //抽稀的数量
iconSize: [23, 30],
iconName: 'monitorvideo',
fieldname: 'gbindexcode'
},
{
zoom: [16, 20], //不同层级下的显示
sliceCount: 1, //抽稀的数量
iconSize: [23, 30],
iconName: 'monitorvideo',
fieldname: 'gbindexcode'
}
]
2)图片边缘裁切的问题处理
在gridlayer绘制的时候判断当前的数据是否会超出绘制边界,超出绘制边界后不予显示(可能会存在数据丢失的问题),也可以移动绘制的位置让其显示完全
_updateIcon: function (layer) {
if (!this._drawing) {
return
}
var icon = layer.options.icon,
options = icon.options,
size = L.point(options.iconSize),
anchor = options.iconAnchor || (size && size.divideBy(2, true)),
p = layer._point.subtract(anchor),
ctx = this._ctx,
img = layer._getImage()
if (img.complete) {
if (p.x + size.x > 256 || p.x < 0 || p.y + size.y > 256 || p.y < 0) {
console.log('图像超出画板边界!')
} else {
ctx.drawImage(img, p.x, p.y, size.x, size.y)
}
} else {
L.DomEvent.on(img, 'load', function () {
if (p.x + size.x > 256 || p.x < 0 || p.y + size.y > 256 || p.y < 0) {
console.log('图像超出画板边界!')
} else {
ctx.drawImage(img, p.x, p.y, size.x, size.y)
}
})
}
this._drawnLayers[layer._leaflet_id] = layer
}
})
3、解决结果
4、参考资料
Leaflet.VectorGrid API reference