From 63ae0fa3514fbcb190349b2d5d98637cd31e4489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kv=C3=A1=C4=8Dek?= Date: Mon, 4 Sep 2023 15:32:23 +0200 Subject: [PATCH] Lepsi podpora elevace terenu --- package.json | 2 + public/mapIcons/currentPosition.png | Bin 0 -> 12828 bytes public/mapIcons/currentPosition32x32.png | Bin 0 -> 1054 bytes quasar.config.js | 1 + src/boot/chartJs.js | 6 + src/components/flights/FlightTrackMap.vue | 93 ++++++++++++--- src/components/map/MapWithMarkers.vue | 52 +++------ src/components/photos/PhotoDetail.vue | 136 +++++++++++----------- src/components/photos/PhotoFormDialog.vue | 2 - src/graphql/fragments/flight.js | 17 ++- yarn.lock | 17 +++ 11 files changed, 197 insertions(+), 129 deletions(-) create mode 100644 public/mapIcons/currentPosition.png create mode 100644 public/mapIcons/currentPosition32x32.png create mode 100644 src/boot/chartJs.js diff --git a/package.json b/package.json index 40a6a25..6287851 100644 --- a/package.json +++ b/package.json @@ -16,11 +16,13 @@ "@vue/apollo-option": "^4.0.0-beta.5", "apollo-upload-client": "^17.0.0", "axios": "^1.4.0", + "chart.js": "^4.4.0", "graphql": "16.6.0", "graphql-tag": "2.12.6", "pinia": "^2.0.33", "quasar": "^2.12.0", "vue": "^3.2.47", + "vue-chartjs": "^5.2.0", "vue-inner-image-zoom": "^2.0.0", "vue-router": "^4.1.6", "vue3-google-map": "^0.15.0" diff --git a/public/mapIcons/currentPosition.png b/public/mapIcons/currentPosition.png new file mode 100644 index 0000000000000000000000000000000000000000..1f295259011e48f81cc53266a6c877882647a546 GIT binary patch literal 12828 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�E;_q^v$fmq;y% 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 oBn{TJvF*K978vv*(X}+pZuzL4D03TNUP5=M^ literal 0 HcmV?d00001 diff --git a/public/mapIcons/currentPosition32x32.png b/public/mapIcons/currentPosition32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..2dac3977479a837058644027b87843336beb5bfd GIT binary patch literal 1054 zcmV+(1mXLMP)EX>4Tx04R}tkvmAkP!xv$riu@$4t5Z6$WWc^-~(~2RVYG*P%E_RU~6lU)_NUeSX9`XORMW|lE0NlEzD*FE)8-9`B<|Gqz~Pt92j2#CZnW|%hd2Jy_M zZE)Tv4zr@H5}y-~n{+|qN3JU#zi}?OEby6OGo6|z4ik%oHdfl06-|wJnmD3rI?Wd{ z9;=+UIBVr9Yu=N;FqG3*mbp%A1PLr+2@++bpo$X8uo0zQC&faF&f`A*Vb?E_OCeVY zj2sK7K!fc1!T;cQwpM;>(wh{D1D!99^Dzo^?E;OO<9r`GPU8d!J_A>J%U`Jjv!A5b zT3X}?7}y3bu3MV22VCv|Lr;cm%B~coCFJwK`x$*x78tw*de^+%n&&uu0Me9I@&-6K z1jY(9d)?>V-R-&k+tbYN2ca)=xty{D4^000SaNLh0L z04^f{04^f|c%?sf00007bV*G`2j>X^5H>GN(u>jn000?uMObu0Z*6U5Zgc=ca%Ew3 zWn>_CX>@2HM@dakSAh-}0005?Nkl(P|Sx6o$VuJL$GbH%+C%t_7obV-bWF zDfk?|Szp9gsPv*QP`ro*ugn${lT8RQ>28h}nZyMxX18X8kRJ}r?6PP6J@cP`1~%AW z&5*nw_`WofL>~d7Do3CITOu3)AJUX4Pd=NMK$4)UJOy5Wz6KKDJ;;T%=4+a!x$>F3 z1kzOF>68l*skjPOL}Wir^>#eYxq1--zo50nNVQrtOJM@4(q0Hj`Ucnm0-yr;ZtT1Hu6ytOO{c)nMFNa~0dNOQ+;}vda+&D@ z4S;w5sI@Jy=i**1!;FAgw-K3{pcbVn3xgmCE)XSVPTxCMzoJ3u5tRIl&H-ELP`QbW(NPkh&YQ)`VaN+8$iWeg|4DR2ZFWKZXr5Aa2V%QWTls;*>jftUCE$lRb}Se`)M zEoeLC&(U!)M_+aM#S7hvt+hrqX{qu|gpn#e;82A2@$p`CeI2jHdjD+4;@9iGu)+U~ YpZe3B1vgA{TL1t607*qoM6N<$f)<|2kN^Mx literal 0 HcmV?d00001 diff --git a/quasar.config.js b/quasar.config.js index b148bc9..ad05f7d 100644 --- a/quasar.config.js +++ b/quasar.config.js @@ -31,6 +31,7 @@ module.exports = configure(function (ctx) { boot: [ "axios", "vueInnerImageZoom", + "chartJs", ], // https://v2.quasar.dev/quasar-cli-vite/quasar-config-js#css diff --git a/src/boot/chartJs.js b/src/boot/chartJs.js new file mode 100644 index 0000000..41daa61 --- /dev/null +++ b/src/boot/chartJs.js @@ -0,0 +1,6 @@ +import {boot} from "quasar/wrappers"; +import {BarElement, CategoryScale, Chart as ChartJS, Filler, Legend, LinearScale, LineElement, PointElement, Title, Tooltip} from "chart.js"; + +export default boot(({app}) => { + ChartJS.register(Title, Tooltip, Legend, PointElement, LineElement, Filler, BarElement, CategoryScale, LinearScale) +}) diff --git a/src/components/flights/FlightTrackMap.vue b/src/components/flights/FlightTrackMap.vue index c3c581c..d091aa3 100644 --- a/src/components/flights/FlightTrackMap.vue +++ b/src/components/flights/FlightTrackMap.vue @@ -2,6 +2,7 @@ import {flight} from "src/composables/objects/flight"; import MapWithMarkers from "components/map/MapWithMarkers.vue"; import {computed, ref} from "vue"; +import {Line} from "vue-chartjs" const props = defineProps({ flight: { @@ -11,24 +12,22 @@ const props = defineProps({ }) -const trackWithGPS = computed(() => { +const mapPhotos = computed(() => flight.value.photos.filter(photo => photo.gpsLatitude && photo.gpsLongitude)); +const poisWithGPS = computed(() => { return flight.value.track.filter(poi => poi.pointOfInterest.gpsLatitude && poi.pointOfInterest.gpsLongitude) }); -const slider = ref(0); - - const pointsOfInterests = computed(() => { const path = [{ label: flight.value.takeoffAirport.name, position: { - lat: flight.value.takeoffAirport.gpsLatitude + (slider.value / 1000), - lng: flight.value.takeoffAirport.gpsLongitude + (slider.value / 1000) + lat: flight.value.takeoffAirport.gpsLatitude, + lng: flight.value.takeoffAirport.gpsLongitude } }]; - for (const poi of trackWithGPS.value) { + for (const poi of poisWithGPS.value) { path.push({ label: poi.pointOfInterest.name, position: {lat: poi.pointOfInterest.gpsLatitude, lng: poi.pointOfInterest.gpsLongitude} @@ -47,33 +46,93 @@ const pointsOfInterests = computed(() => { }); -const mapPhotos = computed(() => { - return flight.value.photos.filter(photo => photo.gpsLatitude && photo.gpsLongitude) -}); +const gpxTrack = flight.value.gpxTrack; const displayMap = computed(() => { return ( - !!flight.value.gpxTrackUrl || + !!gpxTrack || mapPhotos.value.length > 0 || - trackWithGPS.value.length > 0 || + poisWithGPS.value.length > 0 || flight.value.landingAirport.id !== flight.value.takeoffAirport.id ) }); +let chartSpeedData, chartAltitudeData = null; +if (gpxTrack) { + const chartLabels = gpxTrack.time.map(t => { + const datetime = new Date(t); + return datetime.getHours() + ":" + datetime.getMinutes(); + }); + chartSpeedData = { + labels: chartLabels, + datasets: [{ + backgroundColor: "#38bd3e", + borderColor: "#38bd3e", + label: "Rychlost (km/h)", + data: gpxTrack.speed, + pointRadius: 1, + }] + }; + + chartAltitudeData = { + labels: chartLabels, + datasets: [{ + backgroundColor: "#9ae3ff", + borderColor: "#9ae3ff", + label: "Nadmořská výška letu (m)", + data: gpxTrack.altitude, + pointRadius: 1, + }] + }; + + if (gpxTrack.terrainElevation.length > 0) { + chartAltitudeData.datasets.push( + { + backgroundColor: "rgba(148,94,40,0.7)", + borderColor: "#945e28", + label: "Nadmořská výška země (m)", + data: gpxTrack.terrainElevation, + fill: true, + pointRadius: 1, + }); + } +} + + +const currentPositionMarker = ref(null); +const drawCurrentPositionMarker = (e) => { + const res = e.chart.getElementsAtEventForMode(e, 'nearest', {intersect: false},); + if (res.length === 0) { + currentPositionMarker.value = null; + return; + } + const idx = res[0].index; + currentPositionMarker.value = flight.value.gpxTrack.coordinates[idx]; +} + +const chartOptions = { + plugins: { + tooltip: { + mode: 'index', + intersect: false, + } + }, + onClick: drawCurrentPositionMarker, + onHover: drawCurrentPositionMarker, +} diff --git a/src/components/map/MapWithMarkers.vue b/src/components/map/MapWithMarkers.vue index c9783ce..bd1a431 100644 --- a/src/components/map/MapWithMarkers.vue +++ b/src/components/map/MapWithMarkers.vue @@ -6,8 +6,8 @@ import {axios} from "boot/axios"; const props = defineProps({ - gpxTrackUrl: { - type: String, + gpxTrack: { + type: Object, required: false, }, markers: { @@ -15,6 +15,10 @@ const props = defineProps({ required: false, default: () => [] }, + highlightPosition: { + type: Object, + required: false, + }, photos: { type: Array, required: false, @@ -23,35 +27,8 @@ const props = defineProps({ }) const track = ref([]); -const gpxLoading = ref(!!props.gpxTrackUrl); const speed = ref([]); const elevation = ref([]); -onMounted(() => { - if (!props.gpxTrackUrl) { - return; - } - gpxLoading.value = true; - axios.get(props.gpxTrackUrl) - .then(({data}) => (new window.DOMParser()).parseFromString(data, "text/xml")) - .then(doc => { - const points = []; - const nodes = [...doc.getElementsByTagName('trkpt')]; - nodes.forEach(node => { - const lat = parseFloat(node.getAttribute("lat")); - const lng = parseFloat(node.getAttribute("lon")); - - console.log(node.childNodes); - - points.push({lat, lng}); - // speed.value.push(node.getElementsByTagName("extensions").getElementsByTagName("speed")); - // elevation.value.push(node.getElementsByTagName("ele").innerText); - }) - - track.value = points; // puvodne se bounds bralo z tohodle - }) - .finally(() => gpxLoading.value = false); -}); - const bounds = computed(() => { const photosTransformed = props.photos.map(p => ({position: {lat: p.gpsLatitude, lng: p.gpsLongitude}})); @@ -61,22 +38,19 @@ const bounds = computed(() => {