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.", | ||||
|         "customThemeTitle": "Custom themes", | ||||
|         "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", | ||||
|             "downloadAsPdfHelper": "Ideal to print the current map", | ||||
|             "downloadAsPng": "Download as image", | ||||
|  |  | |||
|  | @ -38,7 +38,7 @@ export default interface LineRenderingConfigJson { | |||
|     /** | ||||
|      * 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. | ||||
|      * 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 | ||||
|      */ | ||||
|     dashArray?: string | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ import { TagsFilter } from "../../Logic/Tags/TagsFilter" | |||
| export default class LineRenderingConfig extends WithContextLoader { | ||||
|     public readonly color: TagRenderingConfig | ||||
|     public readonly width: TagRenderingConfig | ||||
|     public readonly dashArray: TagRenderingConfig | ||||
|     public readonly dashArray: string | ||||
|     public readonly lineCap: TagRenderingConfig | ||||
|     public readonly offset: TagRenderingConfig | ||||
|     public readonly fill: TagRenderingConfig | ||||
|  | @ -19,7 +19,7 @@ export default class LineRenderingConfig extends WithContextLoader { | |||
|         super(json, context) | ||||
|         this.color = this.tr("color", "#0000ff") | ||||
|         this.width = this.tr("width", "7") | ||||
|         this.dashArray = this.tr("dashArray", "") | ||||
|         this.dashArray = json.dashArray | ||||
|         this.lineCap = this.tr("lineCap", "round") | ||||
|         this.fill = this.tr("fill", undefined) | ||||
|         this.fillColor = this.tr("fillColor", undefined) | ||||
|  |  | |||
|  | @ -8,6 +8,10 @@ | |||
|   import { SvgToPdf } from "../../Utils/svgToPdf" | ||||
|   import ThemeViewState from "../../Models/ThemeViewState" | ||||
|   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 | ||||
|   let isLoading = state.dataIsLoading | ||||
|  | @ -34,9 +38,21 @@ | |||
|       mapExtent: state.mapProperties.bounds.data, | ||||
|       width: maindiv.offsetWidth, | ||||
|       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> | ||||
| 
 | ||||
| {#if $isLoading} | ||||
|  | @ -107,5 +123,26 @@ | |||
|     {/each} | ||||
|   </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} /> | ||||
| {/if} | ||||
|  |  | |||
|  | @ -357,7 +357,8 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { | |||
|         const targetW = Math.max(element.getBoundingClientRect().width * 4, | ||||
|             ...labels.map(l => l.getBoundingClientRect().width)) | ||||
|         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
 | ||||
|         element.style.width = targetW + "px" | ||||
|         // Force more height to include labels
 | ||||
|  |  | |||
|  | @ -351,7 +351,8 @@ class LineRenderingLayer { | |||
|                         "line-color": ["feature-state", "color"], | ||||
|                         "line-opacity": ["feature-state", "color-opacity"], | ||||
|                         "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: { | ||||
|                         "line-cap": "round" | ||||
|  |  | |||
|  | @ -67,7 +67,6 @@ export class PngMapCreator { | |||
|             const newZoom = settings.zoom.data + Math.log2(pixelRatio) - 1 | ||||
|             const rasterLayerProperties = settings.rasterLayer.data?.properties ?? AvailableRasterLayers.defaultBackgroundLayer.properties | ||||
|             const style =  rasterLayerProperties?.style ?? rasterLayerProperties?.url | ||||
| console.log("Png-map-creator: initing MlMap with style", style, rasterLayerProperties) | ||||
|             const mapElem = new MlMap({ | ||||
|                 container: div.id, | ||||
|                 style, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue