Kurzy po planovane trase
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
import {computed, ref, watch} from "vue";
|
import {computed, ref, watch} from "vue";
|
||||||
import {Marker, CustomMarker, Polyline} from "vue3-google-map";
|
import {Marker, CustomMarker, Polyline} from "vue3-google-map";
|
||||||
import MapWrapper from "components/map/MapWrapper.vue";
|
import MapWrapper from "components/map/MapWrapper.vue";
|
||||||
import {useFlightPlanObjects, useFlightPlanUtils} from "src/composables/flightPlan";
|
import {useFlightPlanCalculations, useFlightPlanObjects, useFlightPlanUtils} from "src/composables/flightPlan";
|
||||||
import {useGeocode} from "src/composables/geocoding";
|
import {useGeocode} from "src/composables/geocoding";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -26,7 +26,7 @@ const props = defineProps({
|
|||||||
type: Number,
|
type: Number,
|
||||||
required: false,
|
required: false,
|
||||||
default: null
|
default: null
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
const emits = defineEmits(["markers-changed", "change-insert-position"]);
|
const emits = defineEmits(["markers-changed", "change-insert-position"]);
|
||||||
|
|
||||||
@@ -34,6 +34,7 @@ const {center} = useGeocode();
|
|||||||
|
|
||||||
const {markerObject, googleMapsMarkerObject, editableNameTypes} = useFlightPlanObjects();
|
const {markerObject, googleMapsMarkerObject, editableNameTypes} = useFlightPlanObjects();
|
||||||
const {getMarkersFrom} = useFlightPlanUtils();
|
const {getMarkersFrom} = useFlightPlanUtils();
|
||||||
|
const {getDuration} = useFlightPlanCalculations();
|
||||||
|
|
||||||
const mapWrap = ref(null);
|
const mapWrap = ref(null);
|
||||||
|
|
||||||
@@ -47,7 +48,18 @@ watch(() => props.flightPlan.track, (newVal) => {
|
|||||||
}, {immediate: true, deep: true});
|
}, {immediate: true, deep: true});
|
||||||
|
|
||||||
const track = computed(() => markers.value.map(m => ({lat: m.gpsLatitude, lng: m.gpsLongitude})));
|
const track = computed(() => markers.value.map(m => ({lat: m.gpsLatitude, lng: m.gpsLongitude})));
|
||||||
|
const trackAids = computed(() => props.flightPlan.track.map(p => ({
|
||||||
|
...p,
|
||||||
|
anchorPoint: 'CENTER',
|
||||||
|
bearing: p.bearing,
|
||||||
|
distance: p.distance,
|
||||||
|
position: {
|
||||||
|
lat: (p.from.gpsLatitude + p.to.gpsLatitude) / 2,
|
||||||
|
lng: (p.from.gpsLongitude + p.to.gpsLongitude) / 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)));
|
||||||
|
const displayTrackAids = ref(true);
|
||||||
|
|
||||||
const addMarker = async (point) => {
|
const addMarker = async (point) => {
|
||||||
if (!point) return;
|
if (!point) return;
|
||||||
@@ -98,6 +110,7 @@ const handleMarkerMove = async (idx, event) => {
|
|||||||
@remove-from-route="removeMarker"
|
@remove-from-route="removeMarker"
|
||||||
>
|
>
|
||||||
<template v-for="(marker, i) in markers" :key="marker.name">
|
<template v-for="(marker, i) in markers" :key="marker.name">
|
||||||
|
<!-- TODO: ve verejne casti by nemel byt draggable!-->
|
||||||
<Marker
|
<Marker
|
||||||
v-if="editableNameTypes.includes(marker.type)"
|
v-if="editableNameTypes.includes(marker.type)"
|
||||||
:options="googleMapsMarkerObject(marker)"
|
:options="googleMapsMarkerObject(marker)"
|
||||||
@@ -105,5 +118,33 @@ const handleMarkerMove = async (idx, event) => {
|
|||||||
@dragend="handleMarkerMove(i, $event.latLng)"
|
@dragend="handleMarkerMove(i, $event.latLng)"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template v-if="displayTrackAids">
|
||||||
|
<template v-for="marker in trackAids" :key="marker">
|
||||||
|
<CustomMarker :options="marker">
|
||||||
|
<div class="track-info" :style='`transform: rotate(${marker.bearing}deg)`'>
|
||||||
|
{{ marker.bearing }}° <br>
|
||||||
|
{{ getDuration(marker.distance, flightPlan.plannedSpeed) }}'
|
||||||
|
</div>
|
||||||
|
</CustomMarker>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #layersControlsEnd>
|
||||||
|
<q-checkbox v-model="displayTrackAids" label="Zobrazovat navigaci po trase?"/>
|
||||||
|
</template>
|
||||||
</MapWrapper>
|
</MapWrapper>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.track-info {
|
||||||
|
background: rgba(128, 128, 128, 0.5);
|
||||||
|
color: white;
|
||||||
|
border: solid 2px rgba(0, 0, 0, 0.87);
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px;
|
||||||
|
font-size: 12pt;
|
||||||
|
font-weight: bold;
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import {InfoWindow} from "vue3-google-map";
|
import {CustomMarker, InfoWindow} from "vue3-google-map";
|
||||||
import {useFlightPlanUtils} from "src/composables/flightPlan";
|
import {useFlightPlanUtils} from "src/composables/flightPlan";
|
||||||
import {useGeocode} from "src/composables/geocoding";
|
import {useGeocode} from "src/composables/geocoding";
|
||||||
import {computed, ref, watch} from "vue";
|
import {computed, ref, watch} from "vue";
|
||||||
@@ -98,7 +98,6 @@ const openedTab = ref("info");
|
|||||||
@close="emits('close')"
|
@close="emits('close')"
|
||||||
:options="{position: infoWindow.position}"
|
:options="{position: infoWindow.position}"
|
||||||
>
|
>
|
||||||
|
|
||||||
<q-tabs v-model="openedTab">
|
<q-tabs v-model="openedTab">
|
||||||
<q-tab name="info">{{ title }}</q-tab>
|
<q-tab name="info">{{ title }}</q-tab>
|
||||||
<q-tab name="airspaces" v-if="infoWindow.airspaces?.length">Prostory</q-tab>
|
<q-tab name="airspaces" v-if="infoWindow.airspaces?.length">Prostory</q-tab>
|
||||||
@@ -204,4 +203,15 @@ const openedTab = ref("info");
|
|||||||
|
|
||||||
|
|
||||||
</InfoWindow>
|
</InfoWindow>
|
||||||
|
<CustomMarker :options="{position: infoWindow.position, anchorPoint: 'CENTER'}">
|
||||||
|
<div class="info-window-position"></div>
|
||||||
|
</CustomMarker>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.info-window-position {
|
||||||
|
border: solid 2px orange;
|
||||||
|
border-radius: 50%;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@@ -250,6 +250,7 @@ const isControlsOpened = ref(false);
|
|||||||
:max-zoom="13"
|
:max-zoom="13"
|
||||||
ref="mapRef"
|
ref="mapRef"
|
||||||
>
|
>
|
||||||
|
TODO: pridavani a odebirani z trasy resit pres slot
|
||||||
<AirspaceInfoWindow
|
<AirspaceInfoWindow
|
||||||
v-if="showInfoWindow && infoWindow.active"
|
v-if="showInfoWindow && infoWindow.active"
|
||||||
:info-window="infoWindow"
|
:info-window="infoWindow"
|
||||||
@@ -315,7 +316,7 @@ const isControlsOpened = ref(false);
|
|||||||
|
|
||||||
<Polyline v-if="track" :options="track"/>
|
<Polyline v-if="track" :options="track"/>
|
||||||
|
|
||||||
<CustomControl position="BOTTOM" v-if="showLayerControls" style="width: auto; max-width: 200px">
|
<CustomControl position="TOP" v-if="showLayerControls" style="width: auto; max-width: 200px">
|
||||||
<q-btn
|
<q-btn
|
||||||
@click="isControlsOpened = !isControlsOpened"
|
@click="isControlsOpened = !isControlsOpened"
|
||||||
:icon="isControlsOpened ? 'layers_clear' : 'layers'"
|
:icon="isControlsOpened ? 'layers_clear' : 'layers'"
|
||||||
@@ -323,12 +324,12 @@ const isControlsOpened = ref(false);
|
|||||||
text-color="grey-9"
|
text-color="grey-9"
|
||||||
round
|
round
|
||||||
size="sm"
|
size="sm"
|
||||||
:class="{'q-mb-lg': !isControlsOpened}"
|
class="q-my-md"
|
||||||
>
|
>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
<q-card
|
<q-card
|
||||||
v-if="isControlsOpened"
|
v-if="isControlsOpened"
|
||||||
class="q-my-md q-mx-auto q-px-lg"
|
class="q-px-lg"
|
||||||
style="max-width: 30%; min-width: 200px;"
|
style="max-width: 30%; min-width: 200px;"
|
||||||
>
|
>
|
||||||
<template v-for="(airspaceLayer, key) in airspaceLayers" :key="airspaceLayer">
|
<template v-for="(airspaceLayer, key) in airspaceLayers" :key="airspaceLayer">
|
||||||
@@ -341,16 +342,20 @@ const isControlsOpened = ref(false);
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
<div class="q-my-lg">
|
||||||
|
Zobrazit prostory od GND do výšky {{ altitudeLimitFormatted(maxAltitude, 'ft') }}
|
||||||
<q-slider
|
<q-slider
|
||||||
class="q-my-md"
|
|
||||||
v-model.number="maxAltitude"
|
v-model.number="maxAltitude"
|
||||||
:min="1000"
|
:min="1000"
|
||||||
:max="15000"
|
:max="15000"
|
||||||
label
|
label
|
||||||
label-always
|
|
||||||
:label-value="altitudeLimitFormatted(maxAltitude, 'ft')"
|
:label-value="altitudeLimitFormatted(maxAltitude, 'ft')"
|
||||||
:step="1000"
|
:step="1000"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<slot name="layersControlsEnd"></slot>
|
||||||
|
|
||||||
</q-card>
|
</q-card>
|
||||||
</CustomControl>
|
</CustomControl>
|
||||||
</GoogleMap>
|
</GoogleMap>
|
||||||
|
|||||||
Reference in New Issue
Block a user