2023-06-14 20:39:36 +02:00
import { Store , UIEventSource } from "../../Logic/UIEventSource"
import type { Map as MLMap } from "maplibre-gl"
import { Map as MlMap , SourceSpecification } from "maplibre-gl"
2023-06-29 00:24:19 +02:00
import { AvailableRasterLayers , RasterLayerPolygon } from "../../Models/RasterLayers"
2023-06-14 20:39:36 +02:00
import { Utils } from "../../Utils"
import { BBox } from "../../Logic/BBox"
import { ExportableMap , MapProperties } from "../../Models/MapProperties"
2023-03-24 19:21:15 +01:00
import SvelteUIElement from "../Base/SvelteUIElement"
import MaplibreMap from "./MaplibreMap.svelte"
2023-06-14 20:39:36 +02:00
import { RasterLayerProperties } from "../../Models/RasterLayerProperties"
import * as htmltoimage from "html-to-image"
2023-03-23 00:58:21 +01:00
2023-03-24 19:21:15 +01:00
/ * *
* The 'MapLibreAdaptor' bridges 'MapLibre' with the various properties of the ` MapProperties `
* /
2023-04-19 03:20:49 +02:00
export class MapLibreAdaptor implements MapProperties , ExportableMap {
2023-03-24 19:21:15 +01:00
private static maplibre_control_handlers = [
2023-03-25 02:48:24 +01:00
// "scrollZoom",
// "boxZoom",
// "doubleClickZoom",
2023-03-24 19:21:15 +01:00
"dragRotate" ,
"dragPan" ,
"keyboard" ,
"touchZoomRotate" ,
]
2023-03-28 05:13:48 +02:00
private static maplibre_zoom_handlers = [
"scrollZoom" ,
"boxZoom" ,
"doubleClickZoom" ,
"touchZoomRotate" ,
]
2023-03-23 00:58:21 +01:00
readonly location : UIEventSource < { lon : number ; lat : number } >
readonly zoom : UIEventSource < number >
2023-03-28 05:13:48 +02:00
readonly bounds : UIEventSource < BBox >
2023-03-23 00:58:21 +01:00
readonly rasterLayer : UIEventSource < RasterLayerPolygon | undefined >
2023-03-24 19:21:15 +01:00
readonly maxbounds : UIEventSource < BBox | undefined >
readonly allowMoving : UIEventSource < true | boolean | undefined >
2023-03-28 05:13:48 +02:00
readonly allowZooming : UIEventSource < true | boolean | undefined >
readonly lastClickLocation : Store < undefined | { lon : number ; lat : number } >
2023-04-06 01:33:08 +02:00
readonly minzoom : UIEventSource < number >
2023-04-21 01:53:24 +02:00
readonly maxzoom : UIEventSource < number >
2023-03-11 02:37:07 +01:00
private readonly _maplibreMap : Store < MLMap >
2023-03-23 00:58:21 +01:00
/ * *
* Used for internal bookkeeping ( to remove a rasterLayer when done loading )
* @private
* /
private _currentRasterLayer : string
2023-03-24 19:21:15 +01:00
2023-03-29 17:21:20 +02:00
constructor ( maplibreMap : Store < MLMap > , state? : Partial < MapProperties > ) {
2023-03-11 02:37:07 +01:00
this . _maplibreMap = maplibreMap
2023-06-07 22:46:41 +02:00
this . location = state ? . location ? ? new UIEventSource ( undefined )
2023-06-04 00:43:32 +02:00
if ( this . location . data ) {
2023-05-19 10:56:30 +02:00
// The MapLibre adaptor updates the element in the location and then pings them
// Often, code setting this up doesn't expect the object they pass in to be changed, so we create a copy
2023-06-14 20:39:36 +02:00
this . location . setData ( { . . . this . location . data } )
2023-05-19 10:56:30 +02:00
}
2023-03-23 00:58:21 +01:00
this . zoom = state ? . zoom ? ? new UIEventSource ( 1 )
2023-04-06 01:33:08 +02:00
this . minzoom = state ? . minzoom ? ? new UIEventSource ( 0 )
2023-04-21 01:53:24 +02:00
this . maxzoom = state ? . maxzoom ? ? new UIEventSource ( 24 )
2023-03-24 19:21:15 +01:00
this . zoom . addCallbackAndRunD ( ( z ) = > {
2023-04-06 01:33:08 +02:00
if ( z < this . minzoom . data ) {
this . zoom . setData ( this . minzoom . data )
2023-03-24 19:21:15 +01:00
}
2023-04-21 01:53:24 +02:00
const max = Math . min ( 24 , this . maxzoom . data ? ? 24 )
if ( z > max ) {
this . zoom . setData ( max )
2023-03-24 19:21:15 +01:00
}
} )
this . maxbounds = state ? . maxbounds ? ? new UIEventSource ( undefined )
this . allowMoving = state ? . allowMoving ? ? new UIEventSource ( true )
2023-03-28 05:13:48 +02:00
this . allowZooming = state ? . allowZooming ? ? new UIEventSource ( true )
2023-04-06 01:33:08 +02:00
this . bounds = state ? . bounds ? ? new UIEventSource ( undefined )
2023-03-23 00:58:21 +01:00
this . rasterLayer =
state ? . rasterLayer ? ? new UIEventSource < RasterLayerPolygon | undefined > ( undefined )
2023-03-11 02:37:07 +01:00
2023-03-28 05:13:48 +02:00
const lastClickLocation = new UIEventSource < { lon : number ; lat : number } > ( undefined )
this . lastClickLocation = lastClickLocation
2023-03-23 00:58:21 +01:00
const self = this
2023-04-16 03:42:26 +02:00
function handleClick ( e ) {
if ( e . originalEvent [ "consumed" ] ) {
// Workaround, 'ShowPointLayer' sets this flag
return
}
const lon = e . lngLat . lng
const lat = e . lngLat . lat
2023-06-14 20:39:36 +02:00
lastClickLocation . setData ( { lon , lat } )
2023-04-16 03:42:26 +02:00
}
2023-03-11 02:37:07 +01:00
maplibreMap . addCallbackAndRunD ( ( map ) = > {
map . on ( "load" , ( ) = > {
self . setBackground ( )
2023-03-24 19:21:15 +01:00
self . MoveMapToCurrentLoc ( self . location . data )
self . SetZoom ( self . zoom . data )
self . setMaxBounds ( self . maxbounds . data )
self . setAllowMoving ( self . allowMoving . data )
2023-03-28 05:13:48 +02:00
self . setAllowZooming ( self . allowZooming . data )
2023-04-06 01:33:08 +02:00
self . setMinzoom ( self . minzoom . data )
2023-04-21 01:53:24 +02:00
self . setMaxzoom ( self . maxzoom . data )
2023-04-20 01:52:23 +02:00
self . setBounds ( self . bounds . data )
2023-05-18 23:42:03 +02:00
this . updateStores ( true )
2023-03-11 02:37:07 +01:00
} )
2023-03-24 19:21:15 +01:00
self . MoveMapToCurrentLoc ( self . location . data )
self . SetZoom ( self . zoom . data )
self . setMaxBounds ( self . maxbounds . data )
self . setAllowMoving ( self . allowMoving . data )
2023-03-28 05:13:48 +02:00
self . setAllowZooming ( self . allowZooming . data )
2023-04-06 01:33:08 +02:00
self . setMinzoom ( self . minzoom . data )
2023-04-21 01:53:24 +02:00
self . setMaxzoom ( self . maxzoom . data )
2023-04-20 01:52:23 +02:00
self . setBounds ( self . bounds . data )
2023-05-18 23:42:03 +02:00
this . updateStores ( true )
2023-04-06 01:33:08 +02:00
map . on ( "moveend" , ( ) = > this . updateStores ( ) )
2023-03-28 05:13:48 +02:00
map . on ( "click" , ( e ) = > {
2023-04-16 03:42:26 +02:00
handleClick ( e )
} )
map . on ( "contextmenu" , ( e ) = > {
handleClick ( e )
} )
map . on ( "dblclick" , ( e ) = > {
handleClick ( e )
2023-03-28 05:13:48 +02:00
} )
2023-03-11 02:37:07 +01:00
} )
2023-03-23 00:58:21 +01:00
this . rasterLayer . addCallback ( ( _ ) = >
2023-03-24 19:21:15 +01:00
self . setBackground ( ) . catch ( ( _ ) = > {
2023-03-23 00:58:21 +01:00
console . error ( "Could not set background" )
} )
)
this . location . addCallbackAndRunD ( ( loc ) = > {
2023-03-11 02:37:07 +01:00
self . MoveMapToCurrentLoc ( loc )
} )
2023-03-23 00:58:21 +01:00
this . zoom . addCallbackAndRunD ( ( z ) = > self . SetZoom ( z ) )
2023-03-24 19:21:15 +01:00
this . maxbounds . addCallbackAndRun ( ( bbox ) = > self . setMaxBounds ( bbox ) )
this . allowMoving . addCallbackAndRun ( ( allowMoving ) = > self . setAllowMoving ( allowMoving ) )
2023-03-28 05:13:48 +02:00
this . allowZooming . addCallbackAndRun ( ( allowZooming ) = > self . setAllowZooming ( allowZooming ) )
this . bounds . addCallbackAndRunD ( ( bounds ) = > self . setBounds ( bounds ) )
2023-03-11 02:37:07 +01:00
}
2023-03-23 00:58:21 +01:00
2023-03-24 19:21:15 +01:00
/ * *
* Convenience constructor
* /
public static construct ( ) : {
map : Store < MLMap >
ui : SvelteUIElement
mapproperties : MapProperties
} {
const mlmap = new UIEventSource < MlMap > ( undefined )
return {
map : mlmap ,
ui : new SvelteUIElement ( MaplibreMap , {
map : mlmap ,
} ) ,
mapproperties : new MapLibreAdaptor ( mlmap ) ,
2023-03-11 02:37:07 +01:00
}
}
2023-04-21 01:53:24 +02:00
public static prepareWmsSource ( layer : RasterLayerProperties ) : SourceSpecification {
return {
type : "raster" ,
// use the tiles option to specify a 256WMS tile source URL
// https://maplibre.org/maplibre-gl-js-docs/style-spec/sources/
tiles : [ MapLibreAdaptor . prepareWmsURL ( layer . url , layer [ "tile-size" ] ? ? 256 ) ] ,
tileSize : layer [ "tile-size" ] ? ? 256 ,
minzoom : layer [ "min_zoom" ] ? ? 1 ,
maxzoom : layer [ "max_zoom" ] ? ? 25 ,
// scheme: background["type"] === "tms" ? "tms" : "xyz",
}
}
2023-06-14 20:39:36 +02:00
public static setDpi (
drawOn : HTMLCanvasElement ,
ctx : CanvasRenderingContext2D ,
dpiFactor : number
) {
2023-06-07 22:46:41 +02:00
drawOn . style . width = drawOn . style . width || drawOn . width + "px"
drawOn . style . height = drawOn . style . height || drawOn . height + "px"
// Resize canvas and scale future draws.
drawOn . width = Math . ceil ( drawOn . width * dpiFactor )
drawOn . height = Math . ceil ( drawOn . height * dpiFactor )
ctx . scale ( dpiFactor , dpiFactor )
2023-06-14 20:39:36 +02:00
console . log (
"Resizing canvas with setDPI:" ,
drawOn . width ,
drawOn . height ,
drawOn . style . width ,
drawOn . style . height
)
2023-06-07 22:46:41 +02:00
}
2023-03-11 02:37:07 +01:00
/ * *
* Prepares an ELI - URL to be compatible with mapbox
* /
2023-04-21 01:53:24 +02:00
private static prepareWmsURL ( url : string , size : number = 256 ) : string {
2023-03-11 02:37:07 +01:00
// ELI: LAYERS=OGWRGB13_15VL&STYLES=&FORMAT=image/jpeg&CRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}&VERSION=1.3.0&SERVICE=WMS&REQUEST=GetMap
// PROD: SERVICE=WMS&REQUEST=GetMap&LAYERS=OGWRGB13_15VL&STYLES=&FORMAT=image/jpeg&TRANSPARENT=false&VERSION=1.3.0&WIDTH=256&HEIGHT=256&CRS=EPSG:3857&BBOX=488585.4847988467,6590094.830634755,489196.9810251281,6590706.32686104
const toReplace = {
"{bbox}" : "{bbox-epsg-3857}" ,
"{proj}" : "EPSG:3857" ,
"{width}" : "" + size ,
"{height}" : "" + size ,
"{zoom}" : "{z}" ,
}
for ( const key in toReplace ) {
url = url . replace ( new RegExp ( key ) , toReplace [ key ] )
}
const subdomains = url . match ( /\{switch:([a-zA-Z0-9,]*)}/ )
if ( subdomains !== null ) {
const options = subdomains [ 1 ] . split ( "," )
const option = options [ Math . floor ( Math . random ( ) * options . length ) ]
url = url . replace ( subdomains [ 0 ] , option )
}
return url
}
2023-06-04 00:43:32 +02:00
public async exportAsPng ( dpiFactor : number ) : Promise < Blob > {
2023-04-19 03:20:49 +02:00
const map = this . _maplibreMap . data
2023-05-05 02:03:41 +02:00
if ( ! map ) {
2023-04-19 03:20:49 +02:00
return undefined
}
2023-06-04 00:43:32 +02:00
const drawOn = document . createElement ( "canvas" )
drawOn . width = map . getCanvas ( ) . width
drawOn . height = map . getCanvas ( ) . height
2023-04-19 03:20:49 +02:00
2023-06-04 00:43:32 +02:00
console . log ( "Canvas size:" , drawOn . width , drawOn . height )
const ctx = drawOn . getContext ( "2d" )
// Set up CSS size.
2023-06-04 22:52:13 +02:00
MapLibreAdaptor . setDpi ( drawOn , ctx , dpiFactor / map . getPixelRatio ( ) )
2023-04-19 03:20:49 +02:00
2023-06-04 22:52:13 +02:00
await this . exportBackgroundOnCanvas ( ctx )
2023-04-19 03:20:49 +02:00
2023-06-04 00:43:32 +02:00
console . log ( "Getting markers" )
// MapLibreAdaptor.setDpi(drawOn, ctx, 1)
const markers = await this . drawMarkers ( dpiFactor )
2023-06-14 20:39:36 +02:00
console . log (
"Drawing markers (" +
markers . width +
"*" +
markers . height +
") onto drawOn (" +
drawOn . width +
"*" +
drawOn . height +
")"
)
2023-06-04 00:43:32 +02:00
ctx . drawImage ( markers , 0 , 0 , drawOn . width , drawOn . height )
ctx . scale ( dpiFactor , dpiFactor )
this . _maplibreMap . data ? . resize ( )
2023-06-14 20:39:36 +02:00
return await new Promise < Blob > ( ( resolve ) = > drawOn . toBlob ( ( blob ) = > resolve ( blob ) ) )
2023-06-04 00:43:32 +02:00
}
2023-04-19 03:20:49 +02:00
2023-06-04 00:43:32 +02:00
/ * *
* Exports the background map and lines to PNG .
* Markers are _not_ rendered
* /
2023-06-04 22:52:13 +02:00
private async exportBackgroundOnCanvas ( ctx : CanvasRenderingContext2D ) : Promise < void > {
2023-06-04 00:43:32 +02:00
const map = this . _maplibreMap . data
// We draw the maplibre-map onto the canvas. This does not export markers
// Inspiration by https://github.com/mapbox/mapbox-gl-js/issues/2766
2023-04-19 03:20:49 +02:00
2023-06-04 00:43:32 +02:00
// Total hack - see https://stackoverflow.com/questions/42483449/mapbox-gl-js-export-map-to-png-or-pdf
const promise = new Promise < void > ( ( resolve ) = > {
map . once ( "render" , ( ) = > {
ctx . drawImage ( map . getCanvas ( ) , 0 , 0 )
resolve ( )
2023-04-19 03:20:49 +02:00
} )
2023-06-04 00:43:32 +02:00
} )
2023-04-19 03:20:49 +02:00
2023-06-04 00:43:32 +02:00
while ( ! map . isStyleLoaded ( ) ) {
console . log ( "Waiting to fully load the style..." )
await Utils . waitFor ( 100 )
2023-04-19 03:20:49 +02:00
}
2023-06-04 00:43:32 +02:00
map . triggerRepaint ( )
await promise
map . resize ( )
}
2023-04-19 03:20:49 +02:00
2023-06-04 00:43:32 +02:00
private async drawMarkers ( dpiFactor : number ) : Promise < HTMLCanvasElement > {
const map = this . _maplibreMap . data
if ( ! map ) {
return undefined
2023-04-19 03:20:49 +02:00
}
2023-06-04 00:43:32 +02:00
const width = map . getCanvas ( ) . clientWidth
const height = map . getCanvas ( ) . clientHeight
2023-06-14 20:39:36 +02:00
console . log (
"Canvas size markers:" ,
map . getCanvas ( ) . width ,
map . getCanvas ( ) . height ,
"canvasClientRect:" ,
width ,
height
)
2023-06-04 00:43:32 +02:00
map . getCanvas ( ) . style . display = "none"
const img = await htmltoimage . toCanvas ( map . getCanvasContainer ( ) , {
pixelRatio : dpiFactor ,
canvasWidth : width ,
canvasHeight : height ,
width : width ,
height : height ,
} )
map . getCanvas ( ) . style . display = "unset"
return img
2023-04-19 03:20:49 +02:00
}
2023-05-18 23:42:03 +02:00
private updateStores ( isSetup : boolean = false ) : void {
2023-04-19 03:20:49 +02:00
const map = this . _maplibreMap . data
2023-04-20 17:42:07 +02:00
if ( ! map ) {
2023-04-19 03:20:49 +02:00
return
}
2023-06-14 20:39:36 +02:00
const { lng , lat } = map . getCenter ( )
2023-06-07 22:46:41 +02:00
if ( lng === 0 && lat === 0 ) {
return
}
if ( this . location . data === undefined ) {
2023-06-14 20:39:36 +02:00
this . location . setData ( { lon : lng , lat } )
2023-06-07 22:46:41 +02:00
} else if ( ! isSetup ) {
2023-06-14 23:21:19 +02:00
const lon = map . getCenter ( ) . lng
const lat = map . getCenter ( ) . lat
this . location . setData ( { lon , lat } )
2023-05-18 23:42:03 +02:00
}
2023-04-19 03:20:49 +02:00
this . zoom . setData ( Math . round ( map . getZoom ( ) * 10 ) / 10 )
const bounds = map . getBounds ( )
const bbox = new BBox ( [
[ bounds . getEast ( ) , bounds . getNorth ( ) ] ,
[ bounds . getWest ( ) , bounds . getSouth ( ) ] ,
] )
2023-05-18 23:42:03 +02:00
if ( this . bounds . data === undefined || ! isSetup ) {
this . bounds . setData ( bbox )
}
2023-04-19 03:20:49 +02:00
}
2023-05-18 15:44:54 +02:00
private SetZoom ( z : number ) : void {
2023-03-24 19:21:15 +01:00
const map = this . _maplibreMap . data
if ( ! map || z === undefined ) {
return
}
if ( Math . abs ( map . getZoom ( ) - z ) > 0.01 ) {
map . setZoom ( z )
}
}
2023-05-18 15:44:54 +02:00
private MoveMapToCurrentLoc ( loc : { lat : number ; lon : number } ) : void {
2023-03-24 19:21:15 +01:00
const map = this . _maplibreMap . data
if ( ! map || loc === undefined ) {
return
}
const center = map . getCenter ( )
if ( center . lng !== loc . lon || center . lat !== loc . lat ) {
2023-06-14 20:39:36 +02:00
map . setCenter ( { lng : loc.lon , lat : loc.lat } )
2023-03-24 19:21:15 +01:00
}
}
2023-03-11 02:37:07 +01:00
private async awaitStyleIsLoaded ( ) : Promise < void > {
const map = this . _maplibreMap . data
2023-05-05 02:03:41 +02:00
if ( ! map ) {
2023-03-11 02:37:07 +01:00
return
}
2023-04-06 01:33:08 +02:00
while ( ! map ? . isStyleLoaded ( ) ) {
2023-03-11 02:37:07 +01:00
await Utils . waitFor ( 250 )
}
}
2023-05-18 15:44:54 +02:00
private removeCurrentLayer ( map : MLMap ) : void {
2023-03-11 02:37:07 +01:00
if ( this . _currentRasterLayer ) {
// hide the previous layer
2023-06-29 00:24:19 +02:00
try {
if ( map . getLayer ( this . _currentRasterLayer ) ) {
map . removeLayer ( this . _currentRasterLayer )
}
if ( map . getSource ( this . _currentRasterLayer ) ) {
map . removeSource ( this . _currentRasterLayer )
}
this . _currentRasterLayer = undefined
} catch ( e ) {
console . warn ( "Could not remove the previous layer" )
}
2023-03-11 02:37:07 +01:00
}
}
2023-05-18 15:44:54 +02:00
private async setBackground ( ) : Promise < void > {
2023-03-11 02:37:07 +01:00
const map = this . _maplibreMap . data
2023-05-05 02:03:41 +02:00
if ( ! map ) {
2023-03-11 02:37:07 +01:00
return
}
2023-03-23 00:58:21 +01:00
const background : RasterLayerProperties = this . rasterLayer ? . data ? . properties
2023-06-29 00:24:19 +02:00
console . log ( "Setting background to" , background )
if ( ! background ) {
console . error (
"Attempting to 'setBackground', but the background is" ,
background ,
"for" ,
map . getCanvas ( )
)
2023-03-11 02:37:07 +01:00
return
}
2023-06-29 00:24:19 +02:00
if ( this . _currentRasterLayer === background . id ) {
2023-03-11 02:37:07 +01:00
// already the correct background layer, nothing to do
return
}
2023-06-29 00:24:19 +02:00
2023-03-28 05:13:48 +02:00
if ( ! background ? . url ) {
2023-03-11 02:37:07 +01:00
// no background to set
this . removeCurrentLayer ( map )
return
}
2023-06-14 20:39:36 +02:00
if ( background . type === "vector" ) {
2023-06-29 00:24:19 +02:00
console . log ( "Background layer is vector" , background . id )
this . removeCurrentLayer ( map )
2023-06-14 00:47:09 +02:00
map . setStyle ( background . url )
return
}
2023-06-14 20:39:36 +02:00
let addLayerBeforeId = "aeroway_fill" // this is the first non-landuse item in the stylesheet, we add the raster layer before the roads but above the landuse
2023-06-07 22:46:41 +02:00
if ( background . category === "osmbasedmap" || background . category === "map" ) {
2023-06-07 14:34:58 +02:00
// The background layer is already an OSM-based map or another map, so we don't want anything from the baselayer
2023-06-29 00:24:19 +02:00
addLayerBeforeId = undefined
this . removeCurrentLayer ( map )
} else {
// Make sure that the default maptiler style is loaded as it gives an overlay with roads
const maptiler = AvailableRasterLayers . maplibre . properties
if ( ! map . getSource ( maptiler . id ) ) {
this . removeCurrentLayer ( map )
map . addSource ( maptiler . id , MapLibreAdaptor . prepareWmsSource ( maptiler ) )
map . setStyle ( maptiler . url )
await this . awaitStyleIsLoaded ( )
}
2023-06-07 14:34:58 +02:00
}
2023-06-29 00:24:19 +02:00
if ( ! map . getLayer ( addLayerBeforeId ) ) {
addLayerBeforeId = undefined
}
if ( ! map . getSource ( background . id ) ) {
map . addSource ( background . id , MapLibreAdaptor . prepareWmsSource ( background ) )
}
map . resize ( )
if ( ! map . getLayer ( background . id ) ) {
map . addLayer (
{
id : background.id ,
type : "raster" ,
source : background.id ,
paint : { } ,
} ,
addLayerBeforeId
)
}
2023-03-11 02:37:07 +01:00
await this . awaitStyleIsLoaded ( )
this . removeCurrentLayer ( map )
this . _currentRasterLayer = background ? . id
}
2023-03-24 19:21:15 +01:00
private setMaxBounds ( bbox : undefined | BBox ) {
const map = this . _maplibreMap . data
2023-05-05 02:03:41 +02:00
if ( ! map ) {
2023-03-24 19:21:15 +01:00
return
}
if ( bbox ) {
2023-04-06 01:33:08 +02:00
map ? . setMaxBounds ( bbox . toLngLat ( ) )
2023-03-24 19:21:15 +01:00
} else {
2023-04-06 01:33:08 +02:00
map ? . setMaxBounds ( null )
2023-03-24 19:21:15 +01:00
}
}
private setAllowMoving ( allow : true | boolean | undefined ) {
const map = this . _maplibreMap . data
2023-05-05 02:03:41 +02:00
if ( ! map ) {
2023-03-24 19:21:15 +01:00
return
}
if ( allow === false ) {
for ( const id of MapLibreAdaptor . maplibre_control_handlers ) {
map [ id ] . disable ( )
}
} else {
for ( const id of MapLibreAdaptor . maplibre_control_handlers ) {
map [ id ] . enable ( )
}
}
}
2023-03-28 05:13:48 +02:00
2023-04-06 01:33:08 +02:00
private setMinzoom ( minzoom : number ) {
const map = this . _maplibreMap . data
2023-05-05 02:03:41 +02:00
if ( ! map ) {
2023-04-06 01:33:08 +02:00
return
}
map . setMinZoom ( minzoom )
}
2023-04-21 01:53:24 +02:00
private setMaxzoom ( maxzoom : number ) {
const map = this . _maplibreMap . data
2023-05-05 02:03:41 +02:00
if ( ! map ) {
2023-04-21 01:53:24 +02:00
return
}
map . setMaxZoom ( maxzoom )
}
2023-03-28 05:13:48 +02:00
private setAllowZooming ( allow : true | boolean | undefined ) {
const map = this . _maplibreMap . data
2023-05-05 02:03:41 +02:00
if ( ! map ) {
2023-03-28 05:13:48 +02:00
return
}
if ( allow === false ) {
for ( const id of MapLibreAdaptor . maplibre_zoom_handlers ) {
map [ id ] . disable ( )
}
} else {
for ( const id of MapLibreAdaptor . maplibre_zoom_handlers ) {
map [ id ] . enable ( )
}
}
}
private setBounds ( bounds : BBox ) {
const map = this . _maplibreMap . data
2023-05-05 02:03:41 +02:00
if ( ! map || bounds === undefined ) {
2023-03-28 05:13:48 +02:00
return
}
const oldBounds = map . getBounds ( )
const e = 0.0000001
const hasDiff =
Math . abs ( oldBounds . getWest ( ) - bounds . getWest ( ) ) > e &&
Math . abs ( oldBounds . getEast ( ) - bounds . getEast ( ) ) > e &&
Math . abs ( oldBounds . getNorth ( ) - bounds . getNorth ( ) ) > e &&
Math . abs ( oldBounds . getSouth ( ) - bounds . getSouth ( ) ) > e
if ( ! hasDiff ) {
return
}
map . fitBounds ( bounds . toLngLat ( ) )
}
2023-03-11 02:37:07 +01:00
}