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…
	
	Add table
		Add a link
		
	
		Reference in a new issue