forked from MapComplete/MapComplete
Fix dasharrays, add custom size PNG export
This commit is contained in:
parent
faff07d231
commit
a79675c879
7 changed files with 52 additions and 7 deletions
|
@ -192,6 +192,13 @@
|
||||||
"customThemeIntro": "These are previously visited user-generated themes.",
|
"customThemeIntro": "These are previously visited user-generated themes.",
|
||||||
"customThemeTitle": "Custom themes",
|
"customThemeTitle": "Custom themes",
|
||||||
"download": {
|
"download": {
|
||||||
|
"custom": {
|
||||||
|
"download": "Download PNG of {width}mm wide and {height}mm high",
|
||||||
|
"downloadHelper": "This is meant for print",
|
||||||
|
"height": "Image height (in mm):",
|
||||||
|
"title": "Download an image with a custom width and height",
|
||||||
|
"width": "Image width (in mm): "
|
||||||
|
},
|
||||||
"downloadAsPdf": "Download a PDF of the current map",
|
"downloadAsPdf": "Download a PDF of the current map",
|
||||||
"downloadAsPdfHelper": "Ideal to print the current map",
|
"downloadAsPdfHelper": "Ideal to print the current map",
|
||||||
"downloadAsPng": "Download as image",
|
"downloadAsPng": "Download as image",
|
||||||
|
|
|
@ -38,7 +38,7 @@ export default interface LineRenderingConfigJson {
|
||||||
/**
|
/**
|
||||||
* question: Should a dasharray be used to render the lines?
|
* question: Should a dasharray be used to render the lines?
|
||||||
* The dasharray defines 'pixels of line, pixels of gap, pixels of line, pixels of gap, ...'. For example, `5 6` will be 5 pixels of line followed by a 6 pixel gap.
|
* The dasharray defines 'pixels of line, pixels of gap, pixels of line, pixels of gap, ...'. For example, `5 6` will be 5 pixels of line followed by a 6 pixel gap.
|
||||||
* Cannot be a dynamic property due to a mapbox limitation
|
* Cannot be a dynamic property due to a MapLibre limitation (see https://github.com/maplibre/maplibre-gl-js/issues/1235)
|
||||||
* ifunset: Ways are rendered with a full line
|
* ifunset: Ways are rendered with a full line
|
||||||
*/
|
*/
|
||||||
dashArray?: string
|
dashArray?: string
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { TagsFilter } from "../../Logic/Tags/TagsFilter"
|
||||||
export default class LineRenderingConfig extends WithContextLoader {
|
export default class LineRenderingConfig extends WithContextLoader {
|
||||||
public readonly color: TagRenderingConfig
|
public readonly color: TagRenderingConfig
|
||||||
public readonly width: TagRenderingConfig
|
public readonly width: TagRenderingConfig
|
||||||
public readonly dashArray: TagRenderingConfig
|
public readonly dashArray: string
|
||||||
public readonly lineCap: TagRenderingConfig
|
public readonly lineCap: TagRenderingConfig
|
||||||
public readonly offset: TagRenderingConfig
|
public readonly offset: TagRenderingConfig
|
||||||
public readonly fill: TagRenderingConfig
|
public readonly fill: TagRenderingConfig
|
||||||
|
@ -19,7 +19,7 @@ export default class LineRenderingConfig extends WithContextLoader {
|
||||||
super(json, context)
|
super(json, context)
|
||||||
this.color = this.tr("color", "#0000ff")
|
this.color = this.tr("color", "#0000ff")
|
||||||
this.width = this.tr("width", "7")
|
this.width = this.tr("width", "7")
|
||||||
this.dashArray = this.tr("dashArray", "")
|
this.dashArray = json.dashArray
|
||||||
this.lineCap = this.tr("lineCap", "round")
|
this.lineCap = this.tr("lineCap", "round")
|
||||||
this.fill = this.tr("fill", undefined)
|
this.fill = this.tr("fill", undefined)
|
||||||
this.fillColor = this.tr("fillColor", undefined)
|
this.fillColor = this.tr("fillColor", undefined)
|
||||||
|
|
|
@ -8,6 +8,10 @@
|
||||||
import { SvgToPdf } from "../../Utils/svgToPdf"
|
import { SvgToPdf } from "../../Utils/svgToPdf"
|
||||||
import ThemeViewState from "../../Models/ThemeViewState"
|
import ThemeViewState from "../../Models/ThemeViewState"
|
||||||
import DownloadPdf from "./DownloadPdf.svelte"
|
import DownloadPdf from "./DownloadPdf.svelte"
|
||||||
|
import { PngMapCreator } from "../../Utils/pngMapCreator"
|
||||||
|
import { UIEventSource } from "../../Logic/UIEventSource"
|
||||||
|
import ValidatedInput from "../InputElement/ValidatedInput.svelte"
|
||||||
|
import { LocalStorageSource } from "../../Logic/Web/LocalStorageSource"
|
||||||
|
|
||||||
export let state: ThemeViewState
|
export let state: ThemeViewState
|
||||||
let isLoading = state.dataIsLoading
|
let isLoading = state.dataIsLoading
|
||||||
|
@ -34,9 +38,21 @@
|
||||||
mapExtent: state.mapProperties.bounds.data,
|
mapExtent: state.mapProperties.bounds.data,
|
||||||
width: maindiv.offsetWidth,
|
width: maindiv.offsetWidth,
|
||||||
height: maindiv.offsetHeight,
|
height: maindiv.offsetHeight,
|
||||||
noSelfIntersectingLines,
|
noSelfIntersectingLines
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let customWidth = LocalStorageSource.Get("custom-png-width", "20")
|
||||||
|
let customHeight = LocalStorageSource.Get("custom-png-height", "20")
|
||||||
|
|
||||||
|
async function offerCustomPng(): Promise<Blob> {
|
||||||
|
console.log("Creating a custom size png with dimensions", customWidth.data + "mm *", customHeight.data + "mm")
|
||||||
|
const creator = new PngMapCreator(state, {
|
||||||
|
height: Number(customHeight.data), width: Number(customWidth.data)
|
||||||
|
})
|
||||||
|
return await creator.CreatePng("belowmap")
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $isLoading}
|
{#if $isLoading}
|
||||||
|
@ -107,5 +123,26 @@
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="low-interaction p-2 mt-4">
|
||||||
|
<h3 class="m-0 mb-2">
|
||||||
|
<Tr t={t.custom.title}/></h3>
|
||||||
|
<div class="flex">
|
||||||
|
<Tr t={t.custom.width} />
|
||||||
|
<ValidatedInput {state} type="pnat" value={customWidth} />
|
||||||
|
</div>
|
||||||
|
<div class="flex">
|
||||||
|
<Tr t={t.custom.height} />
|
||||||
|
<ValidatedInput {state} type="pnat" value={customHeight} />
|
||||||
|
</div>
|
||||||
|
<DownloadButton
|
||||||
|
mainText={t.custom.download.Subs({width: $customWidth, height: $customHeight})}
|
||||||
|
helperText={t.custom.downloadHelper}
|
||||||
|
extension="png"
|
||||||
|
construct={() => offerCustomPng()}
|
||||||
|
{state}
|
||||||
|
mimetype="image/png"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Tr cls="link-underline" t={t.licenseInfo} />
|
<Tr cls="link-underline" t={t.licenseInfo} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -357,7 +357,8 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
||||||
const targetW = Math.max(element.getBoundingClientRect().width * 4,
|
const targetW = Math.max(element.getBoundingClientRect().width * 4,
|
||||||
...labels.map(l => l.getBoundingClientRect().width))
|
...labels.map(l => l.getBoundingClientRect().width))
|
||||||
const targetH = element.getBoundingClientRect().height +
|
const targetH = element.getBoundingClientRect().height +
|
||||||
Math.max(...labels.map(l => l.getBoundingClientRect().height))
|
Math.max(...labels.map(l => l.getBoundingClientRect().height * 2 /* A bit of buffer to catch eventual 'margin-top'*/))
|
||||||
|
|
||||||
// Force a wider view for icon badges
|
// Force a wider view for icon badges
|
||||||
element.style.width = targetW + "px"
|
element.style.width = targetW + "px"
|
||||||
// Force more height to include labels
|
// Force more height to include labels
|
||||||
|
|
|
@ -351,7 +351,8 @@ class LineRenderingLayer {
|
||||||
"line-color": ["feature-state", "color"],
|
"line-color": ["feature-state", "color"],
|
||||||
"line-opacity": ["feature-state", "color-opacity"],
|
"line-opacity": ["feature-state", "color-opacity"],
|
||||||
"line-width": ["feature-state", "width"],
|
"line-width": ["feature-state", "width"],
|
||||||
"line-offset": ["feature-state", "offset"]
|
"line-offset": ["feature-state", "offset"],
|
||||||
|
"line-dasharray": this._config.dashArray?.split(" ")?.map(s => Number(s))
|
||||||
},
|
},
|
||||||
layout: {
|
layout: {
|
||||||
"line-cap": "round"
|
"line-cap": "round"
|
||||||
|
|
|
@ -67,7 +67,6 @@ export class PngMapCreator {
|
||||||
const newZoom = settings.zoom.data + Math.log2(pixelRatio) - 1
|
const newZoom = settings.zoom.data + Math.log2(pixelRatio) - 1
|
||||||
const rasterLayerProperties = settings.rasterLayer.data?.properties ?? AvailableRasterLayers.defaultBackgroundLayer.properties
|
const rasterLayerProperties = settings.rasterLayer.data?.properties ?? AvailableRasterLayers.defaultBackgroundLayer.properties
|
||||||
const style = rasterLayerProperties?.style ?? rasterLayerProperties?.url
|
const style = rasterLayerProperties?.style ?? rasterLayerProperties?.url
|
||||||
console.log("Png-map-creator: initing MlMap with style", style, rasterLayerProperties)
|
|
||||||
const mapElem = new MlMap({
|
const mapElem = new MlMap({
|
||||||
container: div.id,
|
container: div.id,
|
||||||
style,
|
style,
|
||||||
|
|
Loading…
Reference in a new issue