From 4cc42c0842af3a3faf923a73b9b508410ec4c448 Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Wed, 14 Jul 2021 16:06:34 +0200 Subject: [PATCH] WIP: length picker --- Svg.ts | 7 +- UI/Input/LengthInput.ts | 117 ++++++++++++++++++++++++++++++++ assets/svg/length-crosshair.svg | 73 ++++++++++++++++++++ test.ts | 9 +-- 4 files changed, 198 insertions(+), 8 deletions(-) create mode 100644 UI/Input/LengthInput.ts create mode 100644 assets/svg/length-crosshair.svg diff --git a/Svg.ts b/Svg.ts index 0266e43e8e..8b1e293075 100644 --- a/Svg.ts +++ b/Svg.ts @@ -184,6 +184,11 @@ export default class Svg { public static layersAdd_svg() { return new Img(Svg.layersAdd, true);} public static layersAdd_ui() { return new FixedUiElement(Svg.layersAdd_img);} + public static length_crosshair = " Created by potrace 1.15, written by Peter Selinger 2001-2017 image/svg+xml " + public static length_crosshair_img = Img.AsImageElement(Svg.length_crosshair) + public static length_crosshair_svg() { return new Img(Svg.length_crosshair, true);} + public static length_crosshair_ui() { return new FixedUiElement(Svg.length_crosshair_img);} + public static logo = " image/svg+xml " public static logo_img = Img.AsImageElement(Svg.logo) public static logo_svg() { return new Img(Svg.logo, true);} @@ -344,4 +349,4 @@ export default class Svg { public static wikipedia_svg() { return new Img(Svg.wikipedia, true);} public static wikipedia_ui() { return new FixedUiElement(Svg.wikipedia_img);} -public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair-empty.svg": Svg.crosshair_empty,"crosshair-locked.svg": Svg.crosshair_locked,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"direction_masked.svg": Svg.direction_masked,"direction_outline.svg": Svg.direction_outline,"direction_stroke.svg": Svg.direction_stroke,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};} +public static All = {"SocialImageForeground.svg": Svg.SocialImageForeground,"add.svg": Svg.add,"addSmall.svg": Svg.addSmall,"ampersand.svg": Svg.ampersand,"arrow-left-smooth.svg": Svg.arrow_left_smooth,"arrow-right-smooth.svg": Svg.arrow_right_smooth,"back.svg": Svg.back,"bug.svg": Svg.bug,"camera-plus.svg": Svg.camera_plus,"checkmark.svg": Svg.checkmark,"circle.svg": Svg.circle,"clock.svg": Svg.clock,"close.svg": Svg.close,"compass.svg": Svg.compass,"cross_bottom_right.svg": Svg.cross_bottom_right,"crosshair-blue-center.svg": Svg.crosshair_blue_center,"crosshair-blue.svg": Svg.crosshair_blue,"crosshair-empty.svg": Svg.crosshair_empty,"crosshair-locked.svg": Svg.crosshair_locked,"crosshair.svg": Svg.crosshair,"delete_icon.svg": Svg.delete_icon,"direction.svg": Svg.direction,"direction_gradient.svg": Svg.direction_gradient,"direction_masked.svg": Svg.direction_masked,"direction_outline.svg": Svg.direction_outline,"direction_stroke.svg": Svg.direction_stroke,"down.svg": Svg.down,"envelope.svg": Svg.envelope,"floppy.svg": Svg.floppy,"gear.svg": Svg.gear,"help.svg": Svg.help,"home.svg": Svg.home,"home_white_bg.svg": Svg.home_white_bg,"josm_logo.svg": Svg.josm_logo,"layers.svg": Svg.layers,"layersAdd.svg": Svg.layersAdd,"length-crosshair.svg": Svg.length_crosshair,"logo.svg": Svg.logo,"logout.svg": Svg.logout,"mapcomplete_logo.svg": Svg.mapcomplete_logo,"mapillary.svg": Svg.mapillary,"mapillary_black.svg": Svg.mapillary_black,"min.svg": Svg.min,"no_checkmark.svg": Svg.no_checkmark,"or.svg": Svg.or,"osm-copyright.svg": Svg.osm_copyright,"osm-logo-us.svg": Svg.osm_logo_us,"osm-logo.svg": Svg.osm_logo,"pencil.svg": Svg.pencil,"phone.svg": Svg.phone,"pin.svg": Svg.pin,"plus.svg": Svg.plus,"pop-out.svg": Svg.pop_out,"reload.svg": Svg.reload,"ring.svg": Svg.ring,"search.svg": Svg.search,"send_email.svg": Svg.send_email,"share.svg": Svg.share,"square.svg": Svg.square,"star.svg": Svg.star,"star_half.svg": Svg.star_half,"star_outline.svg": Svg.star_outline,"star_outline_half.svg": Svg.star_outline_half,"statistics.svg": Svg.statistics,"translate.svg": Svg.translate,"up.svg": Svg.up,"wikidata.svg": Svg.wikidata,"wikimedia-commons-white.svg": Svg.wikimedia_commons_white,"wikipedia.svg": Svg.wikipedia};} diff --git a/UI/Input/LengthInput.ts b/UI/Input/LengthInput.ts new file mode 100644 index 0000000000..82b79ee0f4 --- /dev/null +++ b/UI/Input/LengthInput.ts @@ -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 { + private readonly _location: UIEventSource; + + public readonly IsSelected: UIEventSource = new UIEventSource(false); + private readonly value: UIEventSource; + private background; + + constructor(mapBackground: UIEventSource, + location: UIEventSource, + value?: UIEventSource) { + super(); + this._location = location; + this.value = value ?? new UIEventSource(undefined); + this.background = mapBackground; + } + + GetValue(): UIEventSource { + 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(); + } + } + +} \ No newline at end of file diff --git a/assets/svg/length-crosshair.svg b/assets/svg/length-crosshair.svg new file mode 100644 index 0000000000..6db2cf72b3 --- /dev/null +++ b/assets/svg/length-crosshair.svg @@ -0,0 +1,73 @@ + + + + + +Created by potrace 1.15, written by Peter Selinger 2001-2017 + + + image/svg+xml + + + + + + + + + diff --git a/test.ts b/test.ts index 5d077d3544..23da820f35 100644 --- a/test.ts +++ b/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({ - lat: 51.21576, lon: 3.22001, zoom: 19 - }) -}) +const li = new LengthInput() li.SetStyle("height: 20rem") .AttachTo("maindiv")