forked from MapComplete/MapComplete
		
	WIP: length picker
This commit is contained in:
		
							parent
							
								
									583d1e137f
								
							
						
					
					
						commit
						4cc42c0842
					
				
					 4 changed files with 198 additions and 8 deletions
				
			
		
							
								
								
									
										7
									
								
								Svg.ts
									
										
									
									
									
								
							
							
						
						
									
										7
									
								
								Svg.ts
									
										
									
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										117
									
								
								UI/Input/LengthInput.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								UI/Input/LengthInput.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,117 @@
 | 
			
		|||
import {InputElement} from "./InputElement";
 | 
			
		||||
import {UIEventSource} from "../../Logic/UIEventSource";
 | 
			
		||||
import Combine from "../Base/Combine";
 | 
			
		||||
import Svg from "../../Svg";
 | 
			
		||||
import BaseUIElement from "../BaseUIElement";
 | 
			
		||||
import {FixedUiElement} from "../Base/FixedUiElement";
 | 
			
		||||
import {Utils} from "../../Utils";
 | 
			
		||||
import Loc from "../../Models/Loc";
 | 
			
		||||
import Minimap from "../Base/Minimap";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Selects a length after clicking on the minimap, in meters
 | 
			
		||||
 */
 | 
			
		||||
export default class LengthInput extends InputElement<string> {
 | 
			
		||||
    private readonly _location: UIEventSource<Loc>;
 | 
			
		||||
 | 
			
		||||
    public readonly IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
			
		||||
    private readonly value: UIEventSource<string>;
 | 
			
		||||
    private background;
 | 
			
		||||
 | 
			
		||||
    constructor(mapBackground: UIEventSource<any>, 
 | 
			
		||||
                location: UIEventSource<Loc>,
 | 
			
		||||
                value?: UIEventSource<string>) {
 | 
			
		||||
        super();
 | 
			
		||||
        this._location = location;
 | 
			
		||||
        this.value = value ?? new UIEventSource<string>(undefined);
 | 
			
		||||
        this.background = mapBackground;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    GetValue(): UIEventSource<string> {
 | 
			
		||||
        return this.value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    IsValid(str: string): boolean {
 | 
			
		||||
        const t = Number(str);
 | 
			
		||||
        return !isNaN(t) && t >= 0 && t <= 360;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected InnerConstructElement(): HTMLElement {
 | 
			
		||||
 | 
			
		||||
        let map: BaseUIElement = new FixedUiElement("")
 | 
			
		||||
        if (!Utils.runningFromConsole) {
 | 
			
		||||
            map = new Minimap({
 | 
			
		||||
                background: this.background,
 | 
			
		||||
                allowMoving: true,
 | 
			
		||||
                location: this._location
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const element = new Combine([
 | 
			
		||||
             Svg.direction_stroke_svg().SetStyle(
 | 
			
		||||
                `position: absolute;top: 0;left: 0;width: 100%;height: 100%;transform:rotate(${this.value.data ?? 0}deg);`)
 | 
			
		||||
                .SetClass("direction-svg relative")
 | 
			
		||||
                 .SetStyle("z-index: 1000"),
 | 
			
		||||
            map.SetClass("w-full h-full absolute top-0 left-O rounded-full overflow-hidden"),
 | 
			
		||||
        ])
 | 
			
		||||
            .SetStyle("position:relative;display:block;width: min(100%, 25em); height: min(100% , 25em); background:white; border: 1px solid black; border-radius: 999em")
 | 
			
		||||
            .ConstructElement()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        this.value.addCallbackAndRunD(rotation => {
 | 
			
		||||
            const cone = element.getElementsByClassName("direction-svg")[0] as HTMLElement
 | 
			
		||||
            cone.style.transform = `rotate(${rotation}deg)`;
 | 
			
		||||
 | 
			
		||||
        })
 | 
			
		||||
 | 
			
		||||
        this.RegisterTriggers(element)
 | 
			
		||||
        element.style.overflow = "hidden"
 | 
			
		||||
 | 
			
		||||
        return element;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private RegisterTriggers(htmlElement: HTMLElement) {
 | 
			
		||||
        const self = this;
 | 
			
		||||
 | 
			
		||||
        function onPosChange(x: number, y: number) {
 | 
			
		||||
            const rect = htmlElement.getBoundingClientRect();
 | 
			
		||||
            const dx = -(rect.left + rect.right) / 2 + x;
 | 
			
		||||
            const dy = (rect.top + rect.bottom) / 2 - y;
 | 
			
		||||
            const angle = 180 * Math.atan2(dy, dx) / Math.PI;
 | 
			
		||||
            const angleGeo = Math.floor((450 - angle) % 360);
 | 
			
		||||
            self.value.setData("" + angleGeo)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        htmlElement.ontouchmove = (ev: TouchEvent) => {
 | 
			
		||||
            onPosChange(ev.touches[0].clientX, ev.touches[0].clientY);
 | 
			
		||||
            ev.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        htmlElement.ontouchstart = (ev: TouchEvent) => {
 | 
			
		||||
            onPosChange(ev.touches[0].clientX, ev.touches[0].clientY);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let isDown = false;
 | 
			
		||||
 | 
			
		||||
        htmlElement.onmousedown = (ev: MouseEvent) => {
 | 
			
		||||
            isDown = true;
 | 
			
		||||
            onPosChange(ev.clientX, ev.clientY);
 | 
			
		||||
            ev.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        htmlElement.onmouseup = (ev) => {
 | 
			
		||||
            isDown = false;
 | 
			
		||||
            ev.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        htmlElement.onmousemove = (ev: MouseEvent) => {
 | 
			
		||||
            if (isDown) {
 | 
			
		||||
                onPosChange(ev.clientX, ev.clientY);
 | 
			
		||||
            }
 | 
			
		||||
            ev.preventDefault();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										73
									
								
								assets/svg/length-crosshair.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								assets/svg/length-crosshair.svg
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,73 @@
 | 
			
		|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
 | 
			
		||||
<svg
 | 
			
		||||
   xmlns:dc="http://purl.org/dc/elements/1.1/"
 | 
			
		||||
   xmlns:cc="http://creativecommons.org/ns#"
 | 
			
		||||
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
 | 
			
		||||
   xmlns:svg="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns="http://www.w3.org/2000/svg"
 | 
			
		||||
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
 | 
			
		||||
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
 | 
			
		||||
   version="1.0"
 | 
			
		||||
   width="859.53607pt"
 | 
			
		||||
   height="858.4754pt"
 | 
			
		||||
   viewBox="0 0 859.53607 858.4754"
 | 
			
		||||
   preserveAspectRatio="xMidYMid meet"
 | 
			
		||||
   id="svg14"
 | 
			
		||||
   sodipodi:docname="length-crosshair.svg"
 | 
			
		||||
   inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
 | 
			
		||||
  <defs
 | 
			
		||||
     id="defs18" />
 | 
			
		||||
  <sodipodi:namedview
 | 
			
		||||
     pagecolor="#ffffff"
 | 
			
		||||
     bordercolor="#666666"
 | 
			
		||||
     borderopacity="1"
 | 
			
		||||
     objecttolerance="10"
 | 
			
		||||
     gridtolerance="10"
 | 
			
		||||
     guidetolerance="10"
 | 
			
		||||
     inkscape:pageopacity="0"
 | 
			
		||||
     inkscape:pageshadow="2"
 | 
			
		||||
     inkscape:window-width="1680"
 | 
			
		||||
     inkscape:window-height="1009"
 | 
			
		||||
     id="namedview16"
 | 
			
		||||
     showgrid="false"
 | 
			
		||||
     showguides="true"
 | 
			
		||||
     inkscape:guide-bbox="true"
 | 
			
		||||
     inkscape:zoom="0.25"
 | 
			
		||||
     inkscape:cx="-448.31847"
 | 
			
		||||
     inkscape:cy="144.08448"
 | 
			
		||||
     inkscape:window-x="0"
 | 
			
		||||
     inkscape:window-y="15"
 | 
			
		||||
     inkscape:window-maximized="1"
 | 
			
		||||
     inkscape:current-layer="svg14"
 | 
			
		||||
     inkscape:snap-smooth-nodes="true" />
 | 
			
		||||
  <metadata
 | 
			
		||||
     id="metadata2">
 | 
			
		||||
Created by potrace 1.15, written by Peter Selinger 2001-2017
 | 
			
		||||
<rdf:RDF>
 | 
			
		||||
  <cc:Work
 | 
			
		||||
     rdf:about="">
 | 
			
		||||
    <dc:format>image/svg+xml</dc:format>
 | 
			
		||||
    <dc:type
 | 
			
		||||
       rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
 | 
			
		||||
    <dc:title />
 | 
			
		||||
  </cc:Work>
 | 
			
		||||
</rdf:RDF>
 | 
			
		||||
</metadata>
 | 
			
		||||
  <ellipse
 | 
			
		||||
     style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:2.83639622;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
 | 
			
		||||
     id="path816"
 | 
			
		||||
     cx="429.76804"
 | 
			
		||||
     cy="429.2377"
 | 
			
		||||
     rx="428.34982"
 | 
			
		||||
     ry="427.81949" />
 | 
			
		||||
  <path
 | 
			
		||||
     style="fill:none;stroke:#000000;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
 | 
			
		||||
     d="M 1.4182129,429.2377 H 858.11788"
 | 
			
		||||
     id="path820"
 | 
			
		||||
     inkscape:connector-curvature="0" />
 | 
			
		||||
  <path
 | 
			
		||||
     style="fill:none;stroke:#000000;stroke-width:0.75px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
 | 
			
		||||
     d="M 429.76803,857.05715 V 1.4182129 v 0"
 | 
			
		||||
     id="path822"
 | 
			
		||||
     inkscape:connector-curvature="0" />
 | 
			
		||||
</svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 2.4 KiB  | 
							
								
								
									
										9
									
								
								test.ts
									
										
									
									
									
								
							
							
						
						
									
										9
									
								
								test.ts
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -10,6 +10,7 @@ import {Translation} from "./UI/i18n/Translation";
 | 
			
		|||
import LocationInput from "./UI/Input/LocationInput";
 | 
			
		||||
import Loc from "./Models/Loc";
 | 
			
		||||
import {VariableUiElement} from "./UI/Base/VariableUIElement";
 | 
			
		||||
import LengthInput from "./UI/Input/LengthInput";
 | 
			
		||||
/*import ValidatedTextField from "./UI/Input/ValidatedTextField";
 | 
			
		||||
import Combine from "./UI/Base/Combine";
 | 
			
		||||
import {VariableUiElement} from "./UI/Base/VariableUIElement";
 | 
			
		||||
| 
						 | 
				
			
			@ -152,13 +153,7 @@ function TestMiniMap() {
 | 
			
		|||
}
 | 
			
		||||
//*/
 | 
			
		||||
 | 
			
		||||
const li = new LocationInput({
 | 
			
		||||
    preferCategory:"photo",
 | 
			
		||||
    centerLocation:
 | 
			
		||||
        new UIEventSource<Loc>({
 | 
			
		||||
            lat: 51.21576, lon: 3.22001, zoom: 19
 | 
			
		||||
        })
 | 
			
		||||
})
 | 
			
		||||
const li = new LengthInput()
 | 
			
		||||
    li.SetStyle("height: 20rem")
 | 
			
		||||
        .AttachTo("maindiv")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue