在使用Leaflet.VectorGrid1.3.0进行点矢量瓦片数据的渲染时,再打开事件交互后,以mouseover为例,当事件添加后,鼠标悬停时,并没有展示相应的数据,反而在控制台下方报错。如下方所示:
本文将介绍在Leaflet.VectorGrid中如何解决点矢量数据加载时,添加事件监听时,发生错误的解决办法,如果您当前也存在这些问题,可以尝试这种解决办法,或许能解决遇到的问题。
一、数据介绍
在进行正式渲染之前,把涉及的数据进行一下简单的介绍。地图上主要包含3中数据,底图采用的高德的在线影像,全国省份数据用的是自己发布的面矢量瓦片,点数据是全国地质灾害的点数据。从灾害类型可分为:小型、中型、大型。
序号 | 说明 | 地址 |
1 | 高德影像 | https://wprd01.is.autonavi.com/appmaptile?&x={x}&y={y}&z={z}&lang=zh_cn&size=2&scl=1&style=6<ype=7 |
2 | 省矢量瓦片 | http://localhost:8086/data/province-4326/{z}/{x}/{y}.pbf |
3 | 地灾瓦片 | http://localhost:8086/data/dizai1228/{z}/{x}/{y}.pbf |
1、矢量瓦片元数据
上述的两种矢量瓦片,省和地灾瓦片是采用本地存储的方式。以省份瓦片为例,其目录如下:
其中,metadata.json是用于描述矢量瓦片的元数据信息,
通过上述的json描述可以知道,矢量瓦片的参数信息,比如中心点位置、边界、数据格式、图层信息包括图层唯一标识符还有属性字段。这些在地图加载的时候是有用的。
这里需要注意一下,对于metajson描述的信息,name和加载瓦片对应的图层不一定是一一对应的,由此要注意,以地灾数据为例。
在进行样式匹配的时候,一定是要用json描述中的vector_layers中的id属性,不要用name避免出现矢量瓦片无法渲染的问题。
二、矢量瓦片渲染
在之前的博客中已经介绍了Leaflet.VectorGrid的渲染方式,这里不在赘述,将主要的代码贴出来。
1、设置瓦片渲染配置
const pbfUrl2 = "http://localhost:8086/data/dizai1228/{z}/{x}/{y}.pbf";
var vectorTileOptions2 = {
layerURL: pbfUrl2,
rendererFactory: L.svg.tile,
tms: false,
interactive: true, //开启VectorGrid触发mouse/pointer事件
vectorTileLayerStyles: vectorTileStyling,
getFeatureId: function(f) {
return f.properties.LineUid;
}
};
在上述的代码中,使用interactive:true开启了相关事件,如果设置为false,那么无法进行事件响应。
2、地图加载及事件绑定
var vectorTile2 = new L.vectorGrid.protobuf(pbfUrl2, vectorTileOptions2).addTo(map);
vectorTile2.on('mouseover', function (e) {
var properties = e.layer.properties;
//console.log(properties);
L.popup()
.setContent(properties.名称 + "<br/>" + properties.灾害类 + "<br/>" + properties.地理位)
.setLatLng(e.latlng)
.openOn(map);
});
3、初始加载
上述代码即完成了地灾矢量瓦片的渲染,将静态html文件使用nginx等服务器进行发布后,可以在浏览器中查看效果。
可以看到,完美的重现了开始提到的问题。
三、问题解决
通过异常可以看到,主要的问题就是点数据的经纬度问题。
刚开始碰到这个问题的时候,我也以为是切的矢量瓦片的问题,因此在数据源上找了很久,然后使用mapbox的框架进行加载,毫无问题。
1、问题查找
带着问题,在尝试了解决办法没有解决后,打开了开源地址,找到了issue,才发现原来已经有前辈替我踩坑了。来看看原贴原始267:
这里提供了一个线索,打开这个连接地址,
2、问题解决
在找到问题之后,在来看看如何解决的,解决方案。
原文是这么描述的,
Point Symbolizer instances inherit from marker or circlemarker, but they lack latlng information, and on mouseover or click, leaflet will error on these features if it finds the getLatLng method, since that indicates it should be treated as a real marker instance, but even though the method is there, the value isn't, so leaflet produces an error.
Maybe these instance should have a latlng, I don't know, this was just an easy fix so that I could continue to use vectorgrid protobuf support with points and have mouseover and click events work.
英文不好,使用某度翻译过来就是:
点符号化器实例继承自标记或circlemarker,但它们缺乏定位信息,当鼠标悬停或单击时,如果传单找到getLatLng方法,它将在这些功能上出错,因为这表明它应该被视为真正的标记实例,但即使该方法存在,值也不存在,因此传单会产生错误。
也许这些实例应该有一个平台,我不知道,这只是一个简单的修复,这样我就可以继续使用vectorgrid protobuf对点的支持,并让鼠标悬停和点击事件正常工作。
getLatlng方法对此有影响,因此我们可以在创建图层时,将getLatlng进行置空。创建图层的方法在Leaflet.VectorGrid.js文件中,大概496行
_createLayer: function(feat, pxPerExtent, layerStyle) {
var layer;
switch (feat.type) {
case 1:
layer = new PointSymbolizer(feat, pxPerExtent);
break;
case 2:
layer = new LineSymbolizer(feat, pxPerExtent);
break;
case 3:
layer = new FillSymbolizer(feat, pxPerExtent);
break;
}
if (this.options.interactive) {
layer.addEventParent(this);
}
return layer;
},
在创建new PointSymbolizer(feat, pxPerExtent);时,将layer.getLatLng = null;即可
3、最后效果
至此,点矢量瓦片不能加载的问题完美解决,感谢开源社区,也许这就是开源的魅力所在。
总结
以上就是本文的主要内容,本文将介绍在Leaflet.VectorGrid中如何解决点矢量数据加载时,添加事件监听时,发生错误的解决办法,如果您当前也存在这些问题,可以尝试这种解决办法,或许能解决遇到的问题。