forked from MapComplete/MapComplete
		
	Add composable icons, add icon badges and overlays, add icon badge to drinking water and cyclofix
This commit is contained in:
		
							parent
							
								
									4f7c25766a
								
							
						
					
					
						commit
						6299c8223e
					
				
					 13 changed files with 518 additions and 172 deletions
				
			
		|  | @ -12,7 +12,6 @@ import {SubstitutedTranslation} from "../../UI/SpecialVisualizations"; | |||
| import {Utils} from "../../Utils"; | ||||
| import Combine from "../../UI/Base/Combine"; | ||||
| import {VariableUiElement} from "../../UI/Base/VariableUIElement"; | ||||
| import {UIElement} from "../../UI/UIElement"; | ||||
| import {UIEventSource} from "../../Logic/UIEventSource"; | ||||
| 
 | ||||
| export default class LayerConfig { | ||||
|  | @ -35,6 +34,7 @@ export default class LayerConfig { | |||
|     titleIcons: TagRenderingConfig[]; | ||||
| 
 | ||||
|     icon: TagRenderingConfig; | ||||
|     iconOverlays: { if: TagsFilter, then: string, badge: boolean }[] | ||||
|     iconSize: TagRenderingConfig; | ||||
|     rotation: TagRenderingConfig; | ||||
|     color: TagRenderingConfig; | ||||
|  | @ -138,6 +138,14 @@ export default class LayerConfig { | |||
| 
 | ||||
|         this.title = tr("title", undefined); | ||||
|         this.icon = tr("icon", Img.AsData(Svg.bug)); | ||||
|         this.iconOverlays = (json.iconOverlays ?? []).map(overlay => { | ||||
|             return { | ||||
|                 if: FromJSON.Tag(overlay.if), | ||||
|                 then: overlay.then, | ||||
|                 badge: overlay.badge ?? false | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         const iconPath = this.icon.GetRenderValue({id: "node/-1"}).txt; | ||||
|         if (iconPath.startsWith(Utils.assets_path)) { | ||||
|             const iconKey = iconPath.substr(Utils.assets_path.length); | ||||
|  | @ -222,23 +230,65 @@ export default class LayerConfig { | |||
|         } | ||||
| 
 | ||||
|         const iconUrlStatic = render(this.icon); | ||||
| 
 | ||||
|         var mappedHtml = tags.map(_ => { | ||||
|         const self = this; | ||||
|         var mappedHtml = tags.map(tags => { | ||||
|             // What do you mean, 'tags' is never read?
 | ||||
|             // It is read implicitly in the 'render' method
 | ||||
|             const iconUrl = render(this.icon); | ||||
|             const rotation = render(this.rotation, "0deg"); | ||||
|             let html = `<img src="${iconUrl}" style="width:100%;height:100%;rotate:${rotation};display:block;" />`; | ||||
|             const iconUrl = render(self.icon); | ||||
|             const rotation = render(self.rotation, "0deg"); | ||||
| 
 | ||||
|             if (iconUrl.startsWith(Utils.assets_path)) { | ||||
|                 const key = iconUrl.substr(Utils.assets_path.length); | ||||
|                 html = new Combine([ | ||||
|                     (Svg.All[key] as string).replace(/stop-color:#000000/g, 'stop-color:' + color) | ||||
|                 ]).SetStyle(`width:100%;height:100%;rotate:${rotation};display:block;`) | ||||
|             let htmlParts = []; | ||||
|             let sourceParts = iconUrl.split(";"); | ||||
| 
 | ||||
|                     .Render(); | ||||
|             function genHtmlFromString(sourcePart: string, style?: string): string { | ||||
|                 style = style ?? `width:100%;height:100%;rotate:${rotation};display:block;position: absolute; top: 0, left: 0`; | ||||
|                 let html = `<img src="${sourcePart}" style="${style}" />`; | ||||
|                 const match = sourcePart.match(/([a-zA-Z0-9_]*):#([0-9a-fA-F]{3,6})/) | ||||
|                 if (match !== null && Svg.All[match[1] + ".svg"] !== undefined) { | ||||
|                     html = new Combine([ | ||||
|                         (Svg.All[match[1] + ".svg"] as string) | ||||
|                             .replace(/#000000/g, "#" + match[2]) | ||||
|                     ]).SetStyle(style).Render(); | ||||
|                 } | ||||
| 
 | ||||
|                 if (sourcePart.startsWith(Utils.assets_path)) { | ||||
|                     const key = sourcePart.substr(Utils.assets_path.length); | ||||
|                     html = new Combine([ | ||||
|                         (Svg.All[key] as string).replace(/stop-color:#000000/g, 'stop-color:' + color) | ||||
|                     ]).SetStyle(style) | ||||
| 
 | ||||
|                         .Render(); | ||||
|                 } | ||||
|                 return html; | ||||
|             } | ||||
|             return html; | ||||
| 
 | ||||
| 
 | ||||
|             for (const sourcePart of sourceParts) { | ||||
|                 htmlParts.push(genHtmlFromString(sourcePart)) | ||||
|             } | ||||
| 
 | ||||
| 
 | ||||
|             let badges = []; | ||||
|             for (const iconOverlay of self.iconOverlays) { | ||||
|                 if (!iconOverlay.if.matchesProperties(tags)) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 if (iconOverlay.badge) { | ||||
|                     badges.push(genHtmlFromString(iconOverlay.then, "display: block;height:100%")) | ||||
|                 } else { | ||||
|                     htmlParts.push(genHtmlFromString(iconOverlay.then)); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (badges.length > 0) { | ||||
|                 const badgesComponent = new Combine(badges) | ||||
| 
 | ||||
|                     .SetStyle("display:flex;height:50%;width:100%;position:absolute;top:50%;left:50%;") | ||||
|                     .Render() | ||||
| 
 | ||||
|                 htmlParts.push(badgesComponent) | ||||
|             } | ||||
|             return htmlParts.join(""); | ||||
|         }) | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -60,6 +60,14 @@ export interface LayerConfigJson { | |||
|      */ | ||||
|     icon?: string | TagRenderingConfigJson; | ||||
| 
 | ||||
|     /** | ||||
|      * IconsOverlays are a list of extra icons/badges to overlay over the icon. | ||||
|      * The 'badge'-toggle changes their behaviour. | ||||
|      * If badge is set, it will be added as a 25% height icon at the bottom right of the icon, with all the badges in a flex layout. | ||||
|      * If badges is false, it'll be a simple overlay | ||||
|      */ | ||||
|     iconOverlays?: {if: AndOrTagConfigJson, then: string, badge?: boolean}[] | ||||
| 
 | ||||
|     /** | ||||
|      * A string containing "width,height" or "width,height,anchorpoint" where anchorpoint is any of 'center', 'top', 'bottom', 'left', 'right', 'bottomleft','topright', ...  | ||||
|      * Default is '40,40,center' | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue