Fix #2024 (or at least: workaround). The main map will now automatically recover from contextLost-events

This commit is contained in:
Pieter Vander Vennet 2024-07-16 16:00:11 +02:00
parent 7d678d95c7
commit 7d0816219f
3 changed files with 35 additions and 4 deletions

View file

@ -469,6 +469,9 @@ export default class ThemeViewState implements SpecialVisualizationState {
public showCurrentLocationOn(map: Store<MlMap>): ShowDataLayer { public showCurrentLocationOn(map: Store<MlMap>): ShowDataLayer {
const id = "gps_location" const id = "gps_location"
const flayerGps = this.layerState.filteredLayers.get(id) const flayerGps = this.layerState.filteredLayers.get(id)
if(flayerGps === undefined){
return
}
const features = this.geolocation.currentUserLocation const features = this.geolocation.currentUserLocation
return new ShowDataLayer(map, { return new ShowDataLayer(map, {
features, features,

View file

@ -22,11 +22,16 @@
export let mapProperties: MapProperties = undefined export let mapProperties: MapProperties = undefined
export let interactive: boolean = true export let interactive: boolean = true
/**
* If many maps are shown (> ~15), Chromium will drop some because of "too Much WEBGL-contexts" (see issue #2024 or https://webglfundamentals.org/webgl/lessons/webgl-multiple-views.html)
* For important maps (e.g. the main map), we want to recover from this
*/
export let autorecovery: boolean = false
let container: HTMLElement let container: HTMLElement
let _map: Map let _map: Map
onMount(() => { function initMap() {
const { lon, lat } = mapProperties?.location?.data ?? { lon: 0, lat: 0 } const { lon, lat } = mapProperties?.location?.data ?? { lon: 0, lat: 0 }
const rasterLayer: RasterLayerProperties = mapProperties?.rasterLayer?.data?.properties const rasterLayer: RasterLayerProperties = mapProperties?.rasterLayer?.data?.properties
@ -56,9 +61,25 @@
window.requestAnimationFrame(() => { window.requestAnimationFrame(() => {
_map.resize() _map.resize()
}) })
_map.on("load", function() { _map.on("load", function() {
_map.resize() _map.resize()
const canvas = _map.getCanvas() const canvas = _map.getCanvas()
canvas.addEventListener("webglcontextlost", (e) => {
console.warn("A MapLibreMap lost their context. Recovery is", autorecovery, e)
try{
_map?.remove()
}catch (e) {
console.log("Could not remove map due to", e)
}
if(autorecovery){
requestAnimationFrame(() => {
console.warn("Attempting map recovery")
_map = new maplibre.Map(options)
initMap()
})
}
})
if (interactive) { if (interactive) {
ariaLabel(canvas, Translations.t.general.visualFeedback.navigation) ariaLabel(canvas, Translations.t.general.visualFeedback.navigation)
canvas.role = "application" canvas.role = "application"
@ -69,7 +90,12 @@
} }
}) })
map.set(_map) map.set(_map)
}) }
onMount(() => initMap())
onDestroy(async () => { onDestroy(async () => {
await Utils.waitFor(100) await Utils.waitFor(100)
requestAnimationFrame( requestAnimationFrame(

View file

@ -213,7 +213,7 @@
<main> <main>
<div class="absolute top-0 left-0 h-screen w-screen overflow-hidden"> <div class="absolute top-0 left-0 h-screen w-screen overflow-hidden">
<MaplibreMap map={maplibremap} mapProperties={mapproperties} /> <MaplibreMap map={maplibremap} mapProperties={mapproperties} autorecovery={true}/>
</div> </div>
{#if $visualFeedback} {#if $visualFeedback}
@ -286,9 +286,11 @@
on:keydown={forwardEventToMap} on:keydown={forwardEventToMap}
htmlElem={openCurrentViewLayerButton} htmlElem={openCurrentViewLayerButton}
> >
<div class="w-8 h-8 cursor-pointer">
<ToSvelte <ToSvelte
construct={() => currentViewLayer.defaultIcon().SetClass("w-8 h-8 cursor-pointer")} construct={() => currentViewLayer.defaultIcon()}
/> />
</div>
</MapControlButton> </MapControlButton>
{/if} {/if}
<ExtraLinkButton {state} /> <ExtraLinkButton {state} />