Refactoring: allow to export the map as PNG

This commit is contained in:
Pieter Vander Vennet 2023-04-19 03:20:49 +02:00
parent e36e9123f3
commit 7f8969146a
16 changed files with 207 additions and 66 deletions

View file

@ -1,5 +1,7 @@
import { Utils } from "../Utils"
export type PriviligedLayerType = typeof Constants.priviliged_layers[number]
export default class Constants {
public static vNumber = "0.30.0"

View file

@ -15,3 +15,7 @@ export interface MapProperties {
readonly allowZooming: UIEventSource<true | boolean>
}
export interface ExportableMap {
exportAsPng(): Promise<Blob>
}

View file

@ -2,6 +2,7 @@ import LayerConfig from "./ThemeConfig/LayerConfig"
import { UIEventSource } from "../Logic/UIEventSource"
import UserRelatedState from "../Logic/State/UserRelatedState"
import { Utils } from "../Utils"
import { LocalStorageSource } from "../Logic/Web/LocalStorageSource"
/**
* Indicates if a menu is open, and if so, which tab is selected;
@ -11,12 +12,12 @@ import { Utils } from "../Utils"
*/
export class MenuState {
private static readonly _themeviewTabs = ["intro", "filters", "download", "copyright"] as const
public readonly themeIsOpened = new UIEventSource(true)
public readonly themeIsOpened: UIEventSource<boolean>
public readonly themeViewTabIndex: UIEventSource<number>
public readonly themeViewTab: UIEventSource<typeof MenuState._themeviewTabs[number]>
private static readonly _menuviewTabs = ["about", "settings", "community", "privacy"] as const
public readonly menuIsOpened = new UIEventSource(false)
public readonly menuIsOpened: UIEventSource<boolean>
public readonly menuViewTabIndex: UIEventSource<number>
public readonly menuViewTab: UIEventSource<typeof MenuState._menuviewTabs[number]>
@ -24,15 +25,20 @@ export class MenuState {
undefined
)
public highlightedUserSetting: UIEventSource<string> = new UIEventSource<string>(undefined)
constructor() {
this.themeViewTabIndex = new UIEventSource(0)
constructor(themeid: string = "") {
if (themeid) {
themeid += "-"
}
this.themeIsOpened = LocalStorageSource.GetParsed(themeid + "thememenuisopened", true)
this.themeViewTabIndex = LocalStorageSource.GetParsed(themeid + "themeviewtabindex", 0)
this.themeViewTab = this.themeViewTabIndex.sync(
(i) => MenuState._themeviewTabs[i],
[],
(str) => MenuState._themeviewTabs.indexOf(<any>str)
)
this.menuViewTabIndex = new UIEventSource(1)
this.menuIsOpened = LocalStorageSource.GetParsed(themeid + "menuisopened", false)
this.menuViewTabIndex = LocalStorageSource.GetParsed(themeid + "menuviewtabindex", 0)
this.menuViewTab = this.menuViewTabIndex.sync(
(i) => MenuState._menuviewTabs[i],
[],

View file

@ -424,7 +424,7 @@ export default class LayerConfig extends WithContextLoader {
if (mapRendering === undefined) {
return undefined
}
return mapRendering.GetBaseIcon(this.GetBaseTags())
return mapRendering.GetBaseIcon(this.GetBaseTags(), { noFullWidth: true })
}
public GetBaseTags(): Record<string, string> {

View file

@ -136,7 +136,10 @@ export default class PointRenderingConfig extends WithContextLoader {
multiSpec: string,
rotation: string,
isBadge: boolean,
defaultElement: BaseUIElement = undefined
defaultElement: BaseUIElement = undefined,
options?: {
noFullWidth?: boolean
}
) {
if (multiSpec === undefined) {
return defaultElement
@ -150,11 +153,21 @@ export default class PointRenderingConfig extends WithContextLoader {
if (elements.length === 0) {
return defaultElement
} else {
return new Combine(elements).SetClass("relative block w-full h-full")
const combine = new Combine(elements).SetClass("relative block")
if (options?.noFullWidth) {
return combine
}
combine.SetClass("w-full h-full")
return combine
}
}
public GetBaseIcon(tags?: Record<string, string>): BaseUIElement {
public GetBaseIcon(
tags?: Record<string, string>,
options?: {
noFullWidth?: boolean
}
): BaseUIElement {
tags = tags ?? { id: "node/-1" }
let defaultPin: BaseUIElement = undefined
if (this.label === undefined) {
@ -176,7 +189,7 @@ export default class PointRenderingConfig extends WithContextLoader {
// This is probably already prepared HTML
return new FixedUiElement(Utils.SubstituteKeys(htmlDefs, tags))
}
return PointRenderingConfig.FromHtmlMulti(htmlDefs, rotation, false, defaultPin)
return PointRenderingConfig.FromHtmlMulti(htmlDefs, rotation, false, defaultPin, options)
}
public GetSimpleIcon(tags: Store<Record<string, string>>): BaseUIElement {

View file

@ -8,7 +8,7 @@ import {
WritableFeatureSource,
} from "../Logic/FeatureSource/FeatureSource"
import { OsmConnection } from "../Logic/Osm/OsmConnection"
import { MapProperties } from "./MapProperties"
import { ExportableMap, MapProperties } from "./MapProperties"
import LayerState from "../Logic/State/LayerState"
import { Feature } from "geojson"
import FullNodeDatabaseSource from "../Logic/FeatureSource/TiledFeatureSource/FullNodeDatabaseSource"
@ -63,7 +63,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
readonly osmConnection: OsmConnection
readonly selectedElement: UIEventSource<Feature>
readonly mapProperties: MapProperties
readonly mapProperties: MapProperties & ExportableMap
readonly dataIsLoading: Store<boolean> // TODO
readonly guistate: MenuState
@ -82,7 +82,7 @@ export default class ThemeViewState implements SpecialVisualizationState {
readonly lastClickObject: WritableFeatureSource
constructor(layout: LayoutConfig) {
this.layout = layout
this.guistate = new MenuState()
this.guistate = new MenuState(layout.id)
this.map = new UIEventSource<MlMap>(undefined)
const initial = new InitialMapPositioning(layout)
this.mapProperties = new MapLibreAdaptor(this.map, initial)