@@ -91,8 +91,12 @@ class InteractiveMap {
9191 minNativeZoom : 3 ,
9292 maxNativeZoom : 5 ,
9393 noWrap : true ,
94- detectRetina : true
94+ detectRetina : true ,
95+ bounds : this . #getTileLayerBounds( url ) ,
9596 }
97+
98+ console . log ( defaults . bounds )
99+
96100 let params = { ...defaults , ...args } ;
97101 params . maxNativeZoom = L . Browser . retina ? params . maxNativeZoom - 1 : params . maxNativeZoom ; // 1 level LOWER for high pixel ratio device.
98102
@@ -524,4 +528,50 @@ class InteractiveMap {
524528
525529 return interactive_layer ;
526530 }
531+
532+ /**
533+ * Tries to read an adjacent tilemapresource.xml and calculate the bounds for this tile layer.
534+ *
535+ * Falls back to 256.
536+ *
537+ * @param {string } url Location of the tiles
538+ */
539+ #getTileLayerBounds( url ) {
540+ if ( window . location . protocol !== 'file:' ) {
541+ // This request has to be synchronous because we can't set the tile layer bounds after initialization
542+ const request = new XMLHttpRequest ( ) ;
543+ request . open ( "GET" , url . replace ( "{z}/{x}/{y}.png" , "tilemapresource.xml" ) , false ) ; // `false` makes the request synchronous
544+ request . send ( null ) ;
545+
546+ if ( request . status === 200 ) {
547+ try {
548+ const parser = new DOMParser ( ) ;
549+ const xmlDoc = parser . parseFromString ( request . responseText , "text/xml" ) ;
550+ const boundingBox = xmlDoc . getElementsByTagName ( "BoundingBox" ) [ 0 ] ;
551+ const reducedBounds = this . #reduceTileSizeBelow256( Math . abs ( boundingBox . getAttribute ( "miny" ) ) , Math . abs ( boundingBox . getAttribute ( "maxx" ) ) ) ;
552+
553+ return L . latLngBounds ( L . latLng ( 0 , 0 ) , L . latLng ( - reducedBounds [ 0 ] , reducedBounds [ 1 ] ) ) ;
554+ } catch {
555+ console . log ( "Failed reading tilemapresource.xml" ) ;
556+ }
557+ }
558+ }
559+
560+ return L . latLngBounds ( L . latLng ( 0 , 0 ) , L . latLng ( - 256 , 256 ) ) ; // gdal2tiles.py never produces tiles larger than 256
561+ }
562+
563+ /**
564+ * Takes a two numbers and halfs them simultaneously until both are smaller than 256.
565+ * @param {number } size1 Number to minify
566+ * @param {number } size2 Number to minify similarly
567+ * @returns [number, number]
568+ */
569+ #reduceTileSizeBelow256( size1 , size2 ) {
570+ while ( size1 > 256 || size2 > 256 ) {
571+ size1 = Math . floor ( size1 / 2 ) ;
572+ size2 = Math . floor ( size2 / 2 ) ;
573+ }
574+
575+ return [ size1 , size2 ] ;
576+ }
527577}
0 commit comments