mapcomplete/Utils/pngMapCreator.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

85 lines
3.1 KiB
TypeScript
Raw Normal View History

import ThemeViewState from "../Models/ThemeViewState"
2023-06-04 22:52:13 +02:00
import {Utils} from "../Utils"
import {UIEventSource} from "../Logic/UIEventSource"
import {Map as MlMap} from "maplibre-gl"
import {MapLibreAdaptor} from "../UI/Map/MapLibreAdaptor";
import {AvailableRasterLayers} from "../Models/RasterLayers";
2022-09-14 12:18:51 +02:00
2022-10-27 01:50:01 +02:00
export interface PngMapCreatorOptions {
readonly width: number
readonly height: number
2022-09-14 12:18:51 +02:00
}
2022-09-12 20:14:03 +02:00
export class PngMapCreator {
private static id = 0
2022-10-27 01:50:01 +02:00
private readonly _options: PngMapCreatorOptions
private readonly _state: ThemeViewState
2022-09-12 20:14:03 +02:00
constructor(state: ThemeViewState, options: PngMapCreatorOptions) {
2022-10-27 01:50:01 +02:00
this._state = state
this._options = options
2022-09-12 20:14:03 +02:00
}
/**
* Creates a base64-encoded PNG image
* @constructor
*/
2023-06-04 22:52:13 +02:00
public async CreatePng(freeComponentId: string, status?: UIEventSource<string>): Promise<Blob> {
const div = document.createElement("div")
div.id = "mapdiv-" + PngMapCreator.id
2023-06-04 22:52:13 +02:00
div.style.width = this._options.width + "mm"
div.style.height = this._options.height + "mm"
PngMapCreator.id++
2023-06-04 23:58:29 +02:00
try {
const layout = this._state.layout
2023-06-04 22:52:13 +02:00
2023-06-04 23:58:29 +02:00
function setState(msg: string) {
status?.setData(layout.id + ": " + msg)
}
setState("Initializing map")
2023-06-04 22:52:13 +02:00
2023-06-04 23:58:29 +02:00
const settings = this._state.mapProperties
const l = settings.location.data
2023-06-04 22:52:13 +02:00
2023-06-04 23:58:29 +02:00
document.getElementById(freeComponentId).appendChild(div)
2023-06-07 00:14:20 +02:00
const pixelRatio = 4
2023-06-04 23:58:29 +02:00
const mapElem = new MlMap({
container: div.id,
style: AvailableRasterLayers.maplibre.properties.url,
center: [l.lon, l.lat],
zoom: settings.zoom.data,
2023-06-07 00:14:20 +02:00
pixelRatio
2023-06-04 23:58:29 +02:00
});
2023-06-04 22:52:13 +02:00
2023-06-04 23:58:29 +02:00
const map = new UIEventSource<MlMap>(mapElem)
const mla = new MapLibreAdaptor(map)
mla.zoom.setData(settings.zoom.data)
mla.location.setData(settings.location.data)
mla.rasterLayer.setData(settings.rasterLayer.data)
mla.allowZooming.setData(false)
mla.allowMoving.setData(false)
2023-06-04 22:52:13 +02:00
2023-06-04 23:58:29 +02:00
this._state?.showNormalDataOn(map)
console.log("Creating a map with size", this._options.width, this._options.height)
2023-06-04 22:52:13 +02:00
2023-06-04 23:58:29 +02:00
setState("Waiting for the data")
await this._state.dataIsLoading.AsPromise((loading) => !loading)
setState("Waiting for styles to be fully loaded")
while (!map?.data?.isStyleLoaded()) {
console.log("Waiting for the style to be loaded...")
await Utils.waitFor(250)
}
// Some extra buffer...
2023-06-07 00:14:20 +02:00
setState("One second pause to make sure all images are loaded...")
2023-06-04 23:58:29 +02:00
await Utils.waitFor(1000)
2023-06-07 00:14:20 +02:00
const dpiFactor = 1
setState("Exporting png (" + this._options.width + "mm * " + this._options.height + "mm , dpiFactor:" + dpiFactor + ", maplibre-canvas-pixelratio: " + pixelRatio + ")")
return await mla.exportAsPng(dpiFactor)
2023-06-04 23:58:29 +02:00
} finally {
div.parentElement.removeChild(div)
}
2022-09-12 20:14:03 +02:00
}
}