@@ -216,6 +216,7 @@ export class FlatMap
216216 #bounds: maplibregl . LngLatBounds
217217 #callbacks: FlatMapCallback [ ] = [ ]
218218 #container: string
219+ #contextLost = false
219220 #created: string
220221 #datasetToFeatureIds: FeatureIdMap = new Map ( )
221222 #details: FlatMapIndex
@@ -230,13 +231,15 @@ export class FlatMap
230231 #mapServer: FlatMapServer
231232 #mapSourceToFeatureIds: FeatureIdMap = new Map ( )
232233 #mapTermGraph: MapTermGraph
234+ #mapTermGraphLoaded = false
233235 #modelToFeatureIds: FeatureIdMap = new Map ( )
234236 #normalisedOrigin: [ number , number ]
235237 #normalised_size: [ number , number ]
236238 #options: MapDescriptionOptions
237239 #pathways: FlatMapPathways
238240 #searchIndex: SearchIndex = new SearchIndex ( )
239241 #startupState = - 1
242+ #style: FlatMapStyleSpecification
240243 #taxon: string | null
241244 #taxonNames = new Map ( )
242245 #taxonToFeatureIds: FeatureIdMap = new Map ( )
@@ -259,6 +262,7 @@ export class FlatMap
259262 this . #layers = mapDescription . layers
260263 this . #options = mapDescription . options
261264 this . #pathways = mapDescription . pathways
265+ this . #style = mapDescription . style
262266 this . #mapTermGraph = new MapTermGraph ( )
263267
264268 const sckanProvenance = mapDescription . details . connectivity
@@ -310,19 +314,75 @@ export class FlatMap
310314 }
311315 }
312316
317+ this . #initialiseMap( )
318+ }
319+
320+
321+ /**
322+ * Force the maplibregl instance to lose it's GL conontext
323+ *
324+ */
325+ forceContextLoss ( )
326+ //=======================================
327+ {
328+ this . #contextLostCallback( )
329+ }
330+
331+ #contextLostCallback( event = undefined )
332+ //=======================================
333+ {
334+ // Clean up some of the resources after the GL context is lost
335+
336+ if ( ! this . #contextLost) {
337+ this . closeMinimap ( )
338+ this . #userInteractions. freeLayersResource ( )
339+ const canvas = this . #map. getCanvas ( )
340+ canvas . removeEventListener ( 'webglcontextlost' , this . #contextLostCallback, false ) ;
341+ this . #map. remove ( )
342+ this . #contextLost = true
343+ this . #startupState = - 1
344+ this . callback ( 'context-lost' , undefined )
345+
346+ // Prevent the browser's default behavior
347+
348+ if ( event ) {
349+ event . preventDefault ( )
350+ }
351+ }
352+ }
353+
354+ /**
355+ * Restore a maplibregl instance after the cotnext is lost
356+ *
357+ */
358+ forceContextRestore ( )
359+ //=======================================
360+ {
361+ if ( this . #contextLost) {
362+ this . #initialiseMap( )
363+ }
364+ }
365+
366+ /**
367+ * Initialise a maplibregl map instance
368+ *
369+ */
370+ #initialiseMap( )
371+ //=======================================
372+ {
313373 // Set options for the map
314374
315375 const mapOptions : maplibregl . MapOptions = {
316- style : mapDescription . style ,
317- container : container ,
376+ style : this . # style,
377+ container : this . # container,
318378 attributionControl : false
319379 }
320380
321- if ( 'maxZoom' in mapDescription . options ) {
322- mapOptions . maxZoom = mapDescription . options . maxZoom ! - 0.001
381+ if ( 'maxZoom' in this . # options) {
382+ mapOptions . maxZoom = this . # options. maxZoom ! - 0.001
323383 }
324- if ( 'minZoom' in mapDescription . options ) {
325- mapOptions . minZoom = mapDescription . options . minZoom
384+ if ( 'minZoom' in this . # options) {
385+ mapOptions . minZoom = this . # options. minZoom
326386 }
327387
328388 // Only show location in address bar when debugging
@@ -331,17 +391,25 @@ export class FlatMap
331391
332392 // Set bounds if it is set in the map's options
333393
334- if ( 'bounds' in mapDescription . options ) {
335- mapOptions . bounds = mapDescription . options . bounds
394+ if ( 'bounds' in this . # options) {
395+ mapOptions . bounds = this . # options. bounds
336396 }
337397
338398 // Create the map
339399
340400 this . #map = new maplibregl . Map ( mapOptions )
341401
402+
403+ // Get the map's canvas element
404+ const canvas = this . #map. getCanvas ( )
405+
406+ // Listen for the 'contextlost' event
407+ canvas . addEventListener ( 'webglcontextlost' , this . #contextLostCallback. bind ( this ) , false ) ;
408+
409+
342410 // Show extra information if debugging
343411
344- if ( mapDescription . options . debug === true ) {
412+ if ( this . # options. debug === true ) {
345413 this . #map. showTileBoundaries = true
346414 this . #map. showCollisionBoxes = true
347415 }
@@ -359,6 +427,7 @@ export class FlatMap
359427 // and map has rendered
360428
361429 const idleSubscription = this . #map. on ( 'idle' , async ( ) => {
430+
362431 if ( this . #startupState === - 1 ) {
363432 this . #startupState = 0
364433 await this . #setupUserInteractions( )
@@ -388,7 +457,16 @@ export class FlatMap
388457 this . #map! . fitBounds ( this . #bounds, { animate : false } )
389458 this . #startupState = 3
390459
460+
461+ // Trigger a context-restored callback
462+
463+ if ( this . #contextLost) {
464+ this . callback ( 'context-restored' , undefined )
465+ this . #contextLost = false
466+ }
467+
391468 idleSubscription . unsubscribe ( )
469+
392470 }
393471 } )
394472 }
@@ -418,9 +496,13 @@ export class FlatMap
418496 // Load icons used for clustered markers
419497 await loadMarkerIcons ( this . #map! )
420498
421- // Load anatomical term hierarchy for the flatmap
422- const termGraph = ( await this . #mapServer. mapTermGraph ( this . #uuid) ) !
423- this . #mapTermGraph. load ( termGraph )
499+ // Load anatomical term hierarchy for the flatmap, this is not required
500+ // again after it has been loaded once
501+ if ( ! this . #mapTermGraphLoaded) {
502+ const termGraph = ( await this . #mapServer. mapTermGraph ( this . #uuid) ) !
503+ this . #mapTermGraph. load ( termGraph )
504+ this . #mapTermGraphLoaded = true
505+ }
424506
425507 // Layers have now loaded so finish setting up
426508 this . #userInteractions = new UserInteractions ( this )
@@ -1036,6 +1118,18 @@ export class FlatMap
10361118 }
10371119 }
10381120
1121+ /**
1122+ * A flag indicating whether gl context is lost
1123+ * @type {Boolean }
1124+ *
1125+ * @group Properties
1126+ */
1127+ get contextLost ( ) : Boolean
1128+ //===================================
1129+ {
1130+ return this . #contextLost
1131+ }
1132+
10391133 /**
10401134 * @group Properties
10411135 */
0 commit comments