forked from MapComplete/MapComplete
Chore: reformat all files with prettier
This commit is contained in:
parent
5757ae5dea
commit
d008dcb54d
214 changed files with 8926 additions and 8196 deletions
|
@ -2,11 +2,9 @@
|
|||
/**
|
||||
* Simple wrapper around the HTML-color field.
|
||||
*/
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
|
||||
export let value: UIEventSource<undefined | string>;
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource"
|
||||
|
||||
export let value: UIEventSource<undefined | string>
|
||||
</script>
|
||||
|
||||
|
||||
<input bind:value={$value} type="color">
|
||||
<input bind:value={$value} type="color" />
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
/**
|
||||
* Simple wrapper around the HTML-date field.
|
||||
*/
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
|
||||
export let value: UIEventSource<undefined | string>;
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource"
|
||||
|
||||
export let value: UIEventSource<undefined | string>
|
||||
</script>
|
||||
|
||||
|
||||
<input bind:value={$value} type="date">
|
||||
<input bind:value={$value} type="date" />
|
||||
|
|
|
@ -1,69 +1,68 @@
|
|||
<script lang="ts">
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import type { MapProperties } from "../../../Models/MapProperties";
|
||||
import { Map as MlMap } from "maplibre-gl";
|
||||
import { MapLibreAdaptor } from "../../Map/MapLibreAdaptor";
|
||||
import MaplibreMap from "../../Map/MaplibreMap.svelte";
|
||||
import ToSvelte from "../../Base/ToSvelte.svelte";
|
||||
import Svg from "../../../Svg.js";
|
||||
import { UIEventSource } from "../../../Logic/UIEventSource"
|
||||
import type { MapProperties } from "../../../Models/MapProperties"
|
||||
import { Map as MlMap } from "maplibre-gl"
|
||||
import { MapLibreAdaptor } from "../../Map/MapLibreAdaptor"
|
||||
import MaplibreMap from "../../Map/MaplibreMap.svelte"
|
||||
import ToSvelte from "../../Base/ToSvelte.svelte"
|
||||
import Svg from "../../../Svg.js"
|
||||
|
||||
/**
|
||||
* A visualisation to pick a direction on a map background.
|
||||
*/
|
||||
export let value: UIEventSource<undefined | string>;
|
||||
export let mapProperties: Partial<MapProperties> & { readonly location: UIEventSource<{ lon: number; lat: number }> };
|
||||
let map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined);
|
||||
let mla = new MapLibreAdaptor(map, mapProperties);
|
||||
export let value: UIEventSource<undefined | string>
|
||||
export let mapProperties: Partial<MapProperties> & {
|
||||
readonly location: UIEventSource<{ lon: number; lat: number }>
|
||||
}
|
||||
let map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined)
|
||||
let mla = new MapLibreAdaptor(map, mapProperties)
|
||||
mla.allowMoving.setData(false)
|
||||
mla.allowZooming.setData(false)
|
||||
let directionElem: HTMLElement | undefined;
|
||||
$: value.addCallbackAndRunD(degrees => {
|
||||
let directionElem: HTMLElement | undefined
|
||||
$: value.addCallbackAndRunD((degrees) => {
|
||||
if (directionElem === undefined) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
directionElem.style.rotate = degrees + "deg";
|
||||
});
|
||||
directionElem.style.rotate = degrees + "deg"
|
||||
})
|
||||
|
||||
let mainElem : HTMLElement
|
||||
let mainElem: HTMLElement
|
||||
function onPosChange(x: number, y: number) {
|
||||
const rect = mainElem.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);
|
||||
value.setData(""+angleGeo);
|
||||
const rect = mainElem.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)
|
||||
value.setData("" + angleGeo)
|
||||
}
|
||||
|
||||
let isDown = false;
|
||||
let isDown = false
|
||||
</script>
|
||||
|
||||
<div bind:this={mainElem} class="relative w-48 h-48 cursor-pointer overflow-hidden"
|
||||
on:click={e => onPosChange(e.x, e.y)}
|
||||
on:mousedown={e => {
|
||||
isDown = true
|
||||
onPosChange(e.clientX, e.clientY)
|
||||
} }
|
||||
on:mousemove={e => {
|
||||
if(isDown){
|
||||
<div
|
||||
bind:this={mainElem}
|
||||
class="relative w-48 h-48 cursor-pointer overflow-hidden"
|
||||
on:click={(e) => onPosChange(e.x, e.y)}
|
||||
on:mousedown={(e) => {
|
||||
isDown = true
|
||||
onPosChange(e.clientX, e.clientY)
|
||||
}}
|
||||
on:mousemove={(e) => {
|
||||
if (isDown) {
|
||||
onPosChange(e.clientX, e.clientY)
|
||||
|
||||
}}}
|
||||
|
||||
on:mouseup={() => {
|
||||
isDown = false
|
||||
} }
|
||||
on:touchmove={e => onPosChange(e.touches[0].clientX, e.touches[0].clientY)}
|
||||
|
||||
|
||||
on:touchstart={e => onPosChange(e.touches[0].clientX, e.touches[0].clientY)}>
|
||||
}
|
||||
}}
|
||||
on:mouseup={() => {
|
||||
isDown = false
|
||||
}}
|
||||
on:touchmove={(e) => onPosChange(e.touches[0].clientX, e.touches[0].clientY)}
|
||||
on:touchstart={(e) => onPosChange(e.touches[0].clientX, e.touches[0].clientY)}
|
||||
>
|
||||
<div class="w-full h-full absolute top-0 left-0 cursor-pointer">
|
||||
<MaplibreMap {map} attribution={false}></MaplibreMap>
|
||||
<MaplibreMap {map} attribution={false} />
|
||||
</div>
|
||||
|
||||
<div bind:this={directionElem} class="absolute w-full h-full top-0 left-0">
|
||||
|
||||
<ToSvelte construct={ Svg.direction_stroke_svg}>
|
||||
|
||||
</ToSvelte>
|
||||
<ToSvelte construct={Svg.direction_stroke_svg} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,139 +1,150 @@
|
|||
<script lang="ts">
|
||||
import { Store, Stores, UIEventSource } from "../../../Logic/UIEventSource";
|
||||
import { Store, Stores, UIEventSource } from "../../../Logic/UIEventSource"
|
||||
|
||||
/**
|
||||
* Given the available floors, shows an elevator to pick a single one
|
||||
*
|
||||
*
|
||||
* This is but the input element, the logic of handling the filter is in 'LevelSelector'
|
||||
*/
|
||||
export let floors: Store<string[]>;
|
||||
export let value: UIEventSource<string>;
|
||||
export let floors: Store<string[]>
|
||||
export let value: UIEventSource<string>
|
||||
|
||||
const HEIGHT = 40;
|
||||
const HEIGHT = 40
|
||||
|
||||
let initialIndex = Math.max(0, floors?.data?.findIndex(f => f === value?.data) ?? 0);
|
||||
let index: UIEventSource<number> = new UIEventSource<number>(initialIndex);
|
||||
let forceIndex: number | undefined = undefined;
|
||||
let top = Math.max(0, initialIndex) * HEIGHT;
|
||||
let elevator: HTMLImageElement;
|
||||
let initialIndex = Math.max(0, floors?.data?.findIndex((f) => f === value?.data) ?? 0)
|
||||
let index: UIEventSource<number> = new UIEventSource<number>(initialIndex)
|
||||
let forceIndex: number | undefined = undefined
|
||||
let top = Math.max(0, initialIndex) * HEIGHT
|
||||
let elevator: HTMLImageElement
|
||||
|
||||
let mouseDown = false;
|
||||
let mouseDown = false
|
||||
|
||||
let container: HTMLElement;
|
||||
let container: HTMLElement
|
||||
|
||||
$:{
|
||||
$: {
|
||||
if (top > 0 || forceIndex !== undefined) {
|
||||
index.setData(closestFloorIndex());
|
||||
value.setData(floors.data[forceIndex ?? closestFloorIndex()]);
|
||||
index.setData(closestFloorIndex())
|
||||
value.setData(floors.data[forceIndex ?? closestFloorIndex()])
|
||||
}
|
||||
}
|
||||
|
||||
function unclick() {
|
||||
mouseDown = false;
|
||||
mouseDown = false
|
||||
}
|
||||
|
||||
function click() {
|
||||
mouseDown = true;
|
||||
mouseDown = true
|
||||
}
|
||||
|
||||
function closestFloorIndex() {
|
||||
return Math.min(floors.data.length - 1, Math.max(0, Math.round(top / HEIGHT)));
|
||||
return Math.min(floors.data.length - 1, Math.max(0, Math.round(top / HEIGHT)))
|
||||
}
|
||||
|
||||
function onMove(e: { movementY: number }) {
|
||||
if (mouseDown) {
|
||||
forceIndex = undefined;
|
||||
const containerY = container.clientTop;
|
||||
const containerMax = containerY + (floors.data.length - 1) * HEIGHT;
|
||||
top = Math.min(Math.max(0, top + e.movementY), containerMax);
|
||||
forceIndex = undefined
|
||||
const containerY = container.clientTop
|
||||
const containerMax = containerY + (floors.data.length - 1) * HEIGHT
|
||||
top = Math.min(Math.max(0, top + e.movementY), containerMax)
|
||||
}
|
||||
}
|
||||
|
||||
let momentum = 0;
|
||||
let momentum = 0
|
||||
|
||||
function stabilize() {
|
||||
// Automatically move the elevator to the closes floor
|
||||
if (mouseDown) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
const target = (forceIndex ?? index.data) * HEIGHT;
|
||||
let diff = target - top;
|
||||
const target = (forceIndex ?? index.data) * HEIGHT
|
||||
let diff = target - top
|
||||
if (diff > 1) {
|
||||
diff /= 3;
|
||||
diff /= 3
|
||||
}
|
||||
const sign = Math.sign(diff);
|
||||
momentum = momentum + sign;
|
||||
let diffR = Math.min(Math.abs(momentum), forceIndex !== undefined ? 9 : 3, Math.abs(diff));
|
||||
momentum = Math.sign(momentum) * Math.min(diffR, Math.abs(momentum));
|
||||
top += sign * diffR;
|
||||
const sign = Math.sign(diff)
|
||||
momentum = momentum + sign
|
||||
let diffR = Math.min(Math.abs(momentum), forceIndex !== undefined ? 9 : 3, Math.abs(diff))
|
||||
momentum = Math.sign(momentum) * Math.min(diffR, Math.abs(momentum))
|
||||
top += sign * diffR
|
||||
if (index.data === forceIndex) {
|
||||
forceIndex = undefined;
|
||||
forceIndex = undefined
|
||||
}
|
||||
top = Math.max(top, 0)
|
||||
}
|
||||
|
||||
Stores.Chronic(50).addCallback(_ => stabilize());
|
||||
floors.addCallback(floors => {
|
||||
forceIndex = floors.findIndex(s => s === value.data)
|
||||
Stores.Chronic(50).addCallback((_) => stabilize())
|
||||
floors.addCallback((floors) => {
|
||||
forceIndex = floors.findIndex((s) => s === value.data)
|
||||
})
|
||||
|
||||
let image: HTMLImageElement;
|
||||
$:{
|
||||
let image: HTMLImageElement
|
||||
$: {
|
||||
if (image) {
|
||||
let lastY = 0;
|
||||
let lastY = 0
|
||||
image.ontouchstart = (e: TouchEvent) => {
|
||||
mouseDown = true;
|
||||
lastY = e.changedTouches[0].clientY;
|
||||
};
|
||||
image.ontouchmove = e => {
|
||||
const y = e.changedTouches[0].clientY;
|
||||
mouseDown = true
|
||||
lastY = e.changedTouches[0].clientY
|
||||
}
|
||||
image.ontouchmove = (e) => {
|
||||
const y = e.changedTouches[0].clientY
|
||||
console.log(y)
|
||||
const movementY = y - lastY;
|
||||
lastY = y;
|
||||
onMove({ movementY });
|
||||
};
|
||||
image.ontouchend = unclick;
|
||||
const movementY = y - lastY
|
||||
lastY = y
|
||||
onMove({ movementY })
|
||||
}
|
||||
image.ontouchend = unclick
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<div bind:this={container} class="relative"
|
||||
style={`height: calc(${HEIGHT}px * ${$floors.length}); width: 96px`}>
|
||||
<div
|
||||
bind:this={container}
|
||||
class="relative"
|
||||
style={`height: calc(${HEIGHT}px * ${$floors.length}); width: 96px`}
|
||||
>
|
||||
<div class="h-full absolute w-min right-0">
|
||||
{#each $floors as floor, i}
|
||||
<button style={`height: ${HEIGHT}px; width: ${HEIGHT}px`}
|
||||
class={"m-0 border-2 border-gray-300 flex content-box justify-center items-center "+(i === (forceIndex ?? $index) ? "selected": "" )
|
||||
}
|
||||
on:click={() => {forceIndex = i}}
|
||||
> {floor}</button>
|
||||
<button
|
||||
style={`height: ${HEIGHT}px; width: ${HEIGHT}px`}
|
||||
class={"m-0 border-2 border-gray-300 flex content-box justify-center items-center " +
|
||||
(i === (forceIndex ?? $index) ? "selected" : "")}
|
||||
on:click={() => {
|
||||
forceIndex = i
|
||||
}}
|
||||
>
|
||||
{floor}
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<div style={`width: ${HEIGHT}px`}>
|
||||
<img bind:this={image} class="draggable" draggable="false" on:mousedown={click} src="./assets/svg/elevator.svg"
|
||||
style={" top: "+top+"px;"} />
|
||||
<img
|
||||
bind:this={image}
|
||||
class="draggable"
|
||||
draggable="false"
|
||||
on:mousedown={click}
|
||||
src="./assets/svg/elevator.svg"
|
||||
style={" top: " + top + "px;"}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<svelte:window on:mousemove={onMove} on:mouseup={unclick} />
|
||||
|
||||
<style>
|
||||
.draggable {
|
||||
user-select: none;
|
||||
cursor: move;
|
||||
position: absolute;
|
||||
user-drag: none;
|
||||
|
||||
.draggable {
|
||||
user-select: none;
|
||||
cursor: move;
|
||||
position: absolute;
|
||||
user-drag: none;
|
||||
|
||||
height: 72px;
|
||||
margin-top: -15px;
|
||||
margin-bottom: -15px;
|
||||
margin-left: -18px;
|
||||
-webkit-user-drag: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
height: 72px;
|
||||
margin-top: -15px;
|
||||
margin-bottom: -15px;
|
||||
margin-left: -18px;
|
||||
-webkit-user-drag: none;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,82 +1,91 @@
|
|||
<script lang="ts">
|
||||
import {Store, UIEventSource} from "../../../Logic/UIEventSource";
|
||||
import type {MapProperties} from "../../../Models/MapProperties";
|
||||
import {Map as MlMap} from "maplibre-gl";
|
||||
import {MapLibreAdaptor} from "../../Map/MapLibreAdaptor";
|
||||
import MaplibreMap from "../../Map/MaplibreMap.svelte";
|
||||
import DragInvitation from "../../Base/DragInvitation.svelte";
|
||||
import {GeoOperations} from "../../../Logic/GeoOperations";
|
||||
import ShowDataLayer from "../../Map/ShowDataLayer";
|
||||
import * as boundsdisplay from "../../../assets/layers/range/range.json"
|
||||
import StaticFeatureSource from "../../../Logic/FeatureSource/Sources/StaticFeatureSource";
|
||||
import * as turf from "@turf/turf"
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
|
||||
import {onDestroy} from "svelte";
|
||||
import { Store, UIEventSource } from "../../../Logic/UIEventSource"
|
||||
import type { MapProperties } from "../../../Models/MapProperties"
|
||||
import { Map as MlMap } from "maplibre-gl"
|
||||
import { MapLibreAdaptor } from "../../Map/MapLibreAdaptor"
|
||||
import MaplibreMap from "../../Map/MaplibreMap.svelte"
|
||||
import DragInvitation from "../../Base/DragInvitation.svelte"
|
||||
import { GeoOperations } from "../../../Logic/GeoOperations"
|
||||
import ShowDataLayer from "../../Map/ShowDataLayer"
|
||||
import * as boundsdisplay from "../../../assets/layers/range/range.json"
|
||||
import StaticFeatureSource from "../../../Logic/FeatureSource/Sources/StaticFeatureSource"
|
||||
import * as turf from "@turf/turf"
|
||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
||||
import { onDestroy } from "svelte"
|
||||
|
||||
/**
|
||||
* A visualisation to pick a location on a map background
|
||||
*/
|
||||
export let value: UIEventSource<{ lon: number, lat: number }>;
|
||||
export let initialCoordinate : {lon: number, lat :number}
|
||||
initialCoordinate = initialCoordinate ?? value.data
|
||||
export let maxDistanceInMeters: number = undefined
|
||||
export let mapProperties: Partial<MapProperties> & {
|
||||
readonly location: UIEventSource<{ lon: number; lat: number }>
|
||||
} = undefined;
|
||||
/**
|
||||
* Called when setup is done, can be used to add more layers to the map
|
||||
*/
|
||||
export let onCreated: (value: Store<{
|
||||
lon: number,
|
||||
lat: number
|
||||
}>, map: Store<MlMap>, mapProperties: MapProperties) => void = undefined
|
||||
/**
|
||||
* A visualisation to pick a location on a map background
|
||||
*/
|
||||
export let value: UIEventSource<{ lon: number; lat: number }>
|
||||
export let initialCoordinate: { lon: number; lat: number }
|
||||
initialCoordinate = initialCoordinate ?? value.data
|
||||
export let maxDistanceInMeters: number = undefined
|
||||
export let mapProperties: Partial<MapProperties> & {
|
||||
readonly location: UIEventSource<{ lon: number; lat: number }>
|
||||
} = undefined
|
||||
/**
|
||||
* Called when setup is done, can be used to add more layers to the map
|
||||
*/
|
||||
export let onCreated: (
|
||||
value: Store<{
|
||||
lon: number
|
||||
lat: number
|
||||
}>,
|
||||
map: Store<MlMap>,
|
||||
mapProperties: MapProperties
|
||||
) => void = undefined
|
||||
|
||||
export let map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined);
|
||||
let mla = new MapLibreAdaptor(map, mapProperties);
|
||||
mapProperties.location.syncWith(value)
|
||||
if (onCreated) {
|
||||
onCreated(value, map, mla)
|
||||
}
|
||||
export let map: UIEventSource<MlMap> = new UIEventSource<MlMap>(undefined)
|
||||
let mla = new MapLibreAdaptor(map, mapProperties)
|
||||
mapProperties.location.syncWith(value)
|
||||
if (onCreated) {
|
||||
onCreated(value, map, mla)
|
||||
}
|
||||
|
||||
let rangeIsShown = false
|
||||
if (maxDistanceInMeters) {
|
||||
onDestroy(mla.location.addCallbackD(newLocation => {
|
||||
const l = [newLocation.lon, newLocation.lat]
|
||||
const c: [number, number] = [initialCoordinate.lon, initialCoordinate.lat]
|
||||
const d = GeoOperations.distanceBetween(l, c)
|
||||
let rangeIsShown = false
|
||||
if (maxDistanceInMeters) {
|
||||
onDestroy(
|
||||
mla.location.addCallbackD((newLocation) => {
|
||||
const l = [newLocation.lon, newLocation.lat]
|
||||
const c: [number, number] = [initialCoordinate.lon, initialCoordinate.lat]
|
||||
const d = GeoOperations.distanceBetween(l, c)
|
||||
console.log("distance is", d, l, c)
|
||||
if (d <= maxDistanceInMeters) {
|
||||
return
|
||||
}
|
||||
// This is too far away - let's move back
|
||||
const correctLocation = GeoOperations.along(c, l, maxDistanceInMeters - 10)
|
||||
window.setTimeout(() => {
|
||||
mla.location.setData({lon: correctLocation[0], lat: correctLocation[1]})
|
||||
}, 25)
|
||||
if (d <= maxDistanceInMeters) {
|
||||
return
|
||||
}
|
||||
// This is too far away - let's move back
|
||||
const correctLocation = GeoOperations.along(c, l, maxDistanceInMeters - 10)
|
||||
window.setTimeout(() => {
|
||||
mla.location.setData({ lon: correctLocation[0], lat: correctLocation[1] })
|
||||
}, 25)
|
||||
|
||||
if (!rangeIsShown) {
|
||||
|
||||
new ShowDataLayer(map, {
|
||||
layer: new LayerConfig(boundsdisplay),
|
||||
features: new StaticFeatureSource(
|
||||
[turf.circle(c, maxDistanceInMeters, {units: "meters", properties: {"range":"yes", id: "0"}}, )]
|
||||
)
|
||||
})
|
||||
rangeIsShown = true
|
||||
}
|
||||
}))
|
||||
}
|
||||
if (!rangeIsShown) {
|
||||
new ShowDataLayer(map, {
|
||||
layer: new LayerConfig(boundsdisplay),
|
||||
features: new StaticFeatureSource([
|
||||
turf.circle(c, maxDistanceInMeters, {
|
||||
units: "meters",
|
||||
properties: { range: "yes", id: "0" },
|
||||
}),
|
||||
]),
|
||||
})
|
||||
rangeIsShown = true
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="relative h-full min-h-32 cursor-pointer overflow-hidden">
|
||||
<div class="w-full h-full absolute top-0 left-0 cursor-pointer">
|
||||
<MaplibreMap {map}/>
|
||||
</div>
|
||||
<div class="w-full h-full absolute top-0 left-0 cursor-pointer">
|
||||
<MaplibreMap {map} />
|
||||
</div>
|
||||
|
||||
<div class="w-full h-full absolute top-0 left-0 p-8 pointer-events-none opacity-50 flex items-center">
|
||||
<img class="h-full max-h-24" src="./assets/svg/move-arrows.svg"/>
|
||||
</div>
|
||||
|
||||
<DragInvitation hideSignal={mla.location.stabilized(3000)}></DragInvitation>
|
||||
<div
|
||||
class="w-full h-full absolute top-0 left-0 p-8 pointer-events-none opacity-50 flex items-center"
|
||||
>
|
||||
<img class="h-full max-h-24" src="./assets/svg/move-arrows.svg" />
|
||||
</div>
|
||||
|
||||
<DragInvitation hideSignal={mla.location.stabilized(3000)} />
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue