kikitte / MVTImageryProvider

A Mapbox style renderer for CesiumJS
MIT License
192 stars 50 forks source link

矢量瓦片上球展示后频繁更改要素属性会导致cesium地球崩溃 #11

Open qiuuuy opened 2 years ago

qiuuuy commented 2 years ago

mbtiles矢量瓦片上球展示后,如果频繁更改某图层的要素属性会导致cesium地球崩溃。以线矢量图层的线宽属性为例,频繁更改线宽度值多次并更新视图,数次以后便会提示错误如下:【很奇怪,每次都是编辑属性15次就崩溃了】 错误3 错误2 错误1

这是控制图层更新的代码: 代码2

kikitte commented 2 years ago

问题确认。Chrome浏览器支持的webgl context数量最多为16个,当webgl context数量超过时浏览器会产生警告并导致渲染失败WARNING: Too many active WebGL contexts. Oldest context will be lost。在你说的情况当中,cesium viewer占用一个webgl context,由于MVTImageryProvider使用mapbox gl js进行渲染,每个MVTImageryProvider会创建一个webgl context,所以第16次重复创建MVTImageryProvider会导致webgl context数量超标。

我考虑在MVTImageryProvider类中添加destroy方法来彻底销毁与当前实例相关的所有资源,包括webgl context.

临时解决这个报错的方法可在MVTImageryProvider添加如下方法,在新建MVTImageryProvider之前销毁上一个不使用的MVTImageryProvider。

destroy() {
   // TODO:该方法尚未释放其他资源

    this.mapboxRenderer._gl.getExtension('WEBGL_lose_context').loseContext();
}
qiuuuy commented 2 years ago

好的,来信已收到!感谢楼主的答复,我先试下您的方案,期待您的最终解决,会继续关注您的,感谢!

---原始邮件--- 发件人: @.> 发送时间: 2022年4月6日(周三) 晚上11:26 收件人: @.>; 抄送: @.**@.>; 主题: Re: [kikitte/MVTImageryProvider] 矢量瓦片上球展示后频繁更改要素属性会导致cesium地球崩溃 (Issue #11)

问题确认。Chrome浏览器支持的webgl context数量最多为16个,当webgl context数量超过时浏览器会产生警告并导致渲染失败WARNING: Too many active WebGL contexts. Oldest context will be lost。在你说的情况当中,cesium viewer占用一个webgl context,由于MVTImageryProvider使用mapbox gl js进行渲染,每个MVTImageryProvider会创建一个webgl context,所以第16次重复创建MVTImageryProvider会导致webgl context数量超标。

我考虑在MVTImageryProvider类中添加destroy方法来彻底销毁与当前实例相关的所有资源,包括webgl context.

临时解决这个报错的方法可在MVTImageryProvider添加如下方法,在新建MVTImageryProvider之前销毁上一个不使用的MVTImageryProvider。 destroy() { // TODO:该方法尚未释放其他资源 this.mapboxRenderer._gl.getExtension('WEBGL_lose_context').loseContext(); }

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you authored the thread.Message ID: @.***>

kikitte commented 2 years ago

已在https://github.com/kikitte/MVTImageryProvider/commit/58d6405fc082adefdca67f4eb64166ec613a18e6 修复

hongfaqiu commented 2 years ago

首先感谢kikitte大神的仓库! 我在使用大神的代码时也发现了这个问题,解决的方法是在模块中创建一个全局变量作为BasicRenderer渲染模板,避免出现16个canvas上下文的浏览器限制,具体实现代码可以参考一下这里 此外,频繁创建MVTImageryProvider类会产生内存占用过大的问题,跟踪内存发现是BasicRenderer中的瓦片缓存没有被释放,所以我在releaseTile的同时释放了未在使用的瓦片缓存,可以看看这处的代码。 这相对于在移除Imagery对象时手动调用一次destory()方法,似乎要稍微简便一些,也期待大神的进一步完善。

kikitte commented 2 years ago

首先感谢kikitte大神的仓库! 我在使用大神的代码时也发现了这个问题,解决的方法是在模块中创建一个全局变量作为BasicRenderer渲染模板,避免出现16个canvas上下文的浏览器限制,具体实现代码可以参考一下这里 此外,频繁创建MVTImageryProvider类会产生内存占用过大的问题,跟踪内存发现是BasicRenderer中的瓦片缓存没有被释放,所以我在releaseTile的同时释放了未在使用的瓦片缓存,可以看看这处的代码。 这相对于在移除Imagery对象时手动调用一次destory()方法,似乎要稍微简便一些,也期待大神的进一步完善。

这种实现方式我考虑的是多个BasicRenderer共用一个canvas可能会造成不可预期的错误,因为我对webgl和mapbox-basic-renderer不熟悉,所以采取保守的方式更为妥当。 这处代码只是放了id为origin的BasicSourceCache对象持有的缓存,具体可看 https://github.com/landtechnologies/Mapbox-vector-tiles-basic-js-renderer/blob/99ba6f3d94eea5dbfed098579f8b8c289854a5a3/src/basic/style.js#L20

如有错误,不吝赐教

hongfaqiu commented 2 years ago

首先感谢kikitte大神的仓库! 我在使用大神的代码时也发现了这个问题,解决的方法是在模块中创建一个全局变量作为BasicRenderer渲染模板,避免出现16个canvas上下文的浏览器限制,具体实现代码可以参考一下这里 此外,频繁创建MVTImageryProvider类会产生内存占用过大的问题,跟踪内存发现是BasicRenderer中的瓦片缓存没有被释放,所以我在releaseTile的同时释放了未在使用的瓦片缓存,可以看看这处的代码。 这相对于在移除Imagery对象时手动调用一次destory()方法,似乎要稍微简便一些,也期待大神的进一步完善。

这种实现方式我考虑的是多个BasicRenderer共用一个canvas可能会造成不可预期的错误,因为我对webgl和mapbox-basic-renderer不熟悉,所以采取保守的方式更为妥当。 这处代码只是放了id为origin的BasicSourceCache对象持有的缓存,具体可看 https://github.com/landtechnologies/Mapbox-vector-tiles-basic-js-renderer/blob/99ba6f3d94eea5dbfed098579f8b8c289854a5a3/src/basic/style.js#L20

如有错误,不吝赐教

感谢大神回复! 我对webgl和canvas也不熟悉,但在我最近的工作中使用这个模块进行pbf渲染,它工作得很好,在上百次频繁的渲染中并没有出现问题,所以我认为多个BasicRenderer共用一个canvas这种做法是可行的。 至于释放缓存的代码,确实有问题,我当时测试时创建的图层id叫origin……感谢大佬指出问题!

wh1246935943 commented 1 year ago

@qiuuuy @hongfaqiu 您好,请问pbf矢量数据渲染出来后,你是怎么修改这些要素的,比如线条宽度。是不是修改这些样式要再次调用new MVTImageryProvider,传入修改后的style,来重新渲染?

hongfaqiu commented 1 year ago

@qiuuuy @hongfaqiu 您好,请问pbf矢量数据渲染出来后,你是怎么修改这些要素的,比如线条宽度。是不是修改这些样式要再次调用new MVTImageryProvider,传入修改后的style,来重新渲染?

是这样的,但是因为瓦片数据已经请求过了,浏览器会有缓存,所以这个重新渲染的过程还是很快的

qiuuuy commented 1 year ago

是的,修改后关闭原来的图层,按照新设置的样式重新渲染一遍图层

---原始邮件--- 发件人: @.> 发送时间: 2023年8月3日(周四) 中午1:53 收件人: @.>; 抄送: @.**@.>; 主题: Re: [kikitte/MVTImageryProvider] 矢量瓦片上球展示后频繁更改要素属性会导致cesium地球崩溃 (Issue #11)

@qiuuuy 您好,请问地图渲染出来后,你是怎么修改这些要素的,比如线条宽度。

— Reply to this email directly, view it on GitHub, or unsubscribe. You are receiving this because you were mentioned.Message ID: @.***>

wh1246935943 commented 1 year ago

@hongfaqiu @qiuuuy 还有两个问题再请教下您 1、pickFeatures这个方法你有用过吗,我在这个上面有描述 2、style.json中配置了两个图层,json如下: image 我现在想实现的是,通过鼠标点击来获取被点击的图层,这该怎么确定,我点了那个图层呢? 上面这个json最终渲染的结果如下图: image 灰色为"2022县矢量_0802152028"这个图层,红色的为“水体面积_10003”图层,我是想通过点击红色区域拿到这个这个区域的信息

hongfaqiu commented 1 year ago

@hongfaqiu @qiuuuy 还有两个问题再请教下您 1、pickFeatures这个方法你有用过吗,我在这个上面有描述 2、style.json中配置了两个图层,json如下: image 我现在想实现的是,通过鼠标点击来获取被点击的图层,这该怎么确定,我点了那个图层呢? 上面这个json最终渲染的结果如下图: image 灰色为"2022县矢量_0802152028"这个图层,红色的为“水体面积_10003”图层,我是想通过点击红色区域拿到这个这个区域的信息

看看构造MVTImageryProvider时有没有传入enablePickFeatures: true?

wh1246935943 commented 1 year ago

@hongfaqiu @qiuuuy 还有两个问题再请教下您 1、pickFeatures这个方法你有用过吗,我在这个上面有描述 2、style.json中配置了两个图层,json如下: image 我现在想实现的是,通过鼠标点击来获取被点击的图层,这该怎么确定,我点了那个图层呢? 上面这个json最终渲染的结果如下图: image 灰色为"2022县矢量_0802152028"这个图层,红色的为“水体面积_10003”图层,我是想通过点击红色区域拿到这个这个区域的信息

看看构造MVTImageryProvider时有没有传入enablePickFeatures: true?

有传入,并且鼠标点击图层时,也有聚焦的效果。

hongfaqiu commented 1 year ago

@wh1246935943 我在你开的issue里面回复了