2022-09-12 20:14:03 +02:00
import FeaturePipelineState from "../Logic/State/FeaturePipelineState" ;
import MinimapImplementation from "../UI/Base/MinimapImplementation" ;
import { UIEventSource } from "../Logic/UIEventSource" ;
import Loc from "../Models/Loc" ;
import ShowDataLayer from "../UI/ShowDataLayer/ShowDataLayer" ;
import { BBox } from "../Logic/BBox" ;
import Minimap from "../UI/Base/Minimap" ;
2022-09-13 00:42:29 +02:00
import AvailableBaseLayers from "../Logic/Actors/AvailableBaseLayers" ;
2022-09-14 12:18:51 +02:00
import { Utils } from "../Utils" ;
export interface PngMapCreatorOptions {
readonly divId : string ; readonly width : number ; readonly height : number ; readonly scaling? : 1 | number ,
readonly dummyMode? : boolean
}
2022-09-12 20:14:03 +02:00
export class PngMapCreator {
2022-09-14 12:18:51 +02:00
private readonly _state : FeaturePipelineState | undefined ;
private readonly _options : PngMapCreatorOptions ;
2022-09-12 20:14:03 +02:00
2022-09-14 12:18:51 +02:00
constructor ( state : FeaturePipelineState | undefined , options : PngMapCreatorOptions ) {
2022-09-12 20:14:03 +02:00
this . _state = state ;
this . _options = { . . . options , scaling : options.scaling ? ? 1 } ;
}
/ * *
* Creates a minimap , waits till all needed tiles are loaded before returning
* @private
* /
private async createAndLoadMinimap ( ) : Promise < MinimapImplementation > {
const state = this . _state ;
const options = this . _options
2022-09-13 00:42:29 +02:00
const baselayer = AvailableBaseLayers . layerOverview . find ( bl = > bl . id === state . layoutToUse . defaultBackgroundId ) ? ? AvailableBaseLayers . osmCarto
2022-09-12 20:14:03 +02:00
return new Promise ( resolve = > {
const minimap = Minimap . createMiniMap ( {
location : new UIEventSource < Loc > ( state . locationControl . data ) , // We remove the link between the old and the new UI-event source as moving the map while the export is running fucks up the screenshot
2022-09-13 00:42:29 +02:00
background : new UIEventSource ( baselayer ) ,
2022-09-12 20:14:03 +02:00
allowMoving : false ,
onFullyLoaded : ( _ ) = >
window . setTimeout ( ( ) = > {
resolve ( < MinimapImplementation > minimap )
} , 250 )
} )
const style = ` width: ${ options . width * options . scaling } mm; height: ${ options . height * options . scaling } mm; `
console . log ( "Style is" , style )
minimap . SetStyle ( style )
minimap . AttachTo ( options . divId )
} )
}
/ * *
* Creates a base64 - encoded PNG image
* @constructor
* /
public async CreatePng ( format : "image" ) : Promise < string > ;
public async CreatePng ( format : "blob" ) : Promise < Blob > ;
public async CreatePng ( format : "image" | "blob" ) : Promise < string | Blob > ;
public async CreatePng ( format : "image" | "blob" ) : Promise < string | Blob > {
// Lets first init the minimap and wait for all background tiles to load
const minimap = await this . createAndLoadMinimap ( )
const state = this . _state
2022-09-14 12:18:51 +02:00
const dummyMode = this . _options . dummyMode ? ? false
console . log ( "Dummy mode is" , dummyMode )
2022-09-12 20:14:03 +02:00
return new Promise < string | Blob > ( resolve = > {
// Next: we prepare the features. Only fully contained features are shown
minimap . leafletMap . addCallbackAndRunD ( async ( leaflet ) = > {
// Ping the featurepipeline to download what is needed
2022-09-14 12:18:51 +02:00
if ( dummyMode ) {
console . warn ( "Dummy mode is active - not loading map layers" )
} else {
const bounds = BBox . fromLeafletBounds ( leaflet . getBounds ( ) . pad ( 0.1 ) . pad ( - state . layoutToUse . widenFactor ) )
state . currentBounds . setData ( bounds )
2022-09-12 20:14:03 +02:00
2022-09-14 12:18:51 +02:00
if ( state . featurePipeline . runningQuery . data ) {
// A query is running!
// Let's wait for it to complete
console . log ( "Waiting for the query to complete" )
await state . featurePipeline . runningQuery . AsPromise ( isRunning = > ! isRunning )
console . log ( "Query has completeted!" )
}
2022-09-12 20:14:03 +02:00
state . featurePipeline . GetTilesPerLayerWithin ( bounds , ( tile ) = > {
if ( tile . layer . layerDef . minzoom > state . locationControl . data . zoom ) {
return
}
if ( tile . layer . layerDef . id . startsWith ( "note_import" ) ) {
// Don't export notes to import
return
}
new ShowDataLayer ( {
features : tile ,
leafletMap : minimap.leafletMap ,
layerToShow : tile.layer.layerDef ,
doShowLayer : tile.layer.isDisplayed ,
state : undefined ,
} )
} )
2022-09-14 14:43:14 +02:00
await Utils . waitFor ( 10000 )
2022-09-14 12:18:51 +02:00
}
minimap . TakeScreenshot ( format ) . then ( result = > {
return resolve ( result ) ;
} )
2022-09-12 20:14:03 +02:00
} )
2022-09-14 12:18:51 +02:00
2022-09-12 20:14:03 +02:00
state . AddAllOverlaysToMap ( minimap . leafletMap )
} )
}
}