Client - display a marker on map when mouse is over the chart
This commit is contained in:
@ -23,7 +23,11 @@
|
||||
{{ t('workouts.DURATION') }}
|
||||
</label>
|
||||
</div>
|
||||
<LineChart v-bind="lineChartProps" class="line-chart" />
|
||||
<LineChart
|
||||
v-bind="lineChartProps"
|
||||
class="line-chart"
|
||||
@mouseleave="emitEmptyCoordinates"
|
||||
/>
|
||||
<div class="no-data-cleaning">
|
||||
{{ t('workouts.NO_DATA_CLEANING') }}
|
||||
</div>
|
||||
@ -40,7 +44,11 @@
|
||||
|
||||
import Card from '@/components/Common/Card.vue'
|
||||
import { IAuthUserProfile } from '@/types/user'
|
||||
import { IWorkoutChartData, IWorkoutState } from '@/types/workouts'
|
||||
import {
|
||||
IWorkoutChartData,
|
||||
IWorkoutState,
|
||||
TCoordinates,
|
||||
} from '@/types/workouts'
|
||||
import { getDatasets } from '@/utils/workouts'
|
||||
|
||||
export default defineComponent({
|
||||
@ -59,7 +67,8 @@
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
emits: ['getCoordinates'],
|
||||
setup(props, { emit }) {
|
||||
const { t } = useI18n()
|
||||
let displayDistance = ref(true)
|
||||
const datasets: ComputedRef<IWorkoutChartData> = computed(() =>
|
||||
@ -76,6 +85,9 @@
|
||||
])
|
||||
),
|
||||
}))
|
||||
const coordinates: ComputedRef<TCoordinates[]> = computed(
|
||||
() => datasets.value.coordinates
|
||||
)
|
||||
const options = computed<ChartOptions<'line'>>(() => ({
|
||||
responsive: true,
|
||||
animation: false,
|
||||
@ -151,6 +163,9 @@
|
||||
: label + ' km/h'
|
||||
},
|
||||
title: function (tooltipItems) {
|
||||
if (tooltipItems.length > 0) {
|
||||
emitCoordinates(coordinates.value[tooltipItems[0].dataIndex])
|
||||
}
|
||||
return tooltipItems.length === 0
|
||||
? ''
|
||||
: displayDistance.value
|
||||
@ -168,6 +183,12 @@
|
||||
function formatDuration(duration: string | number): string {
|
||||
return new Date(+duration * 1000).toISOString().substr(11, 8)
|
||||
}
|
||||
function emitCoordinates(coordinates: TCoordinates) {
|
||||
emit('getCoordinates', coordinates)
|
||||
}
|
||||
function emitEmptyCoordinates() {
|
||||
emitCoordinates({ latitude: null, longitude: null })
|
||||
}
|
||||
|
||||
const { lineChartProps } = useLineChart({
|
||||
chartData,
|
||||
@ -177,6 +198,7 @@
|
||||
displayDistance,
|
||||
lineChartProps,
|
||||
t,
|
||||
emitEmptyCoordinates,
|
||||
updateDisplayDistance,
|
||||
}
|
||||
},
|
||||
|
@ -17,6 +17,10 @@
|
||||
:bounds="bounds"
|
||||
/>
|
||||
<LGeoJson :geojson="geoJson.jsonData" />
|
||||
<LMarker
|
||||
v-if="markerCoordinates.latitude"
|
||||
:lat-lng="[markerCoordinates.latitude, markerCoordinates.longitude]"
|
||||
/>
|
||||
</LMap>
|
||||
</div>
|
||||
<div v-else class="no-map">{{ t('workouts.NO_MAP') }}</div>
|
||||
@ -25,13 +29,13 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { gpx } from '@tmcw/togeojson'
|
||||
import { LGeoJson, LMap, LTileLayer } from '@vue-leaflet/vue-leaflet'
|
||||
import { LGeoJson, LMap, LMarker, LTileLayer } from '@vue-leaflet/vue-leaflet'
|
||||
import { ComputedRef, PropType, computed, defineComponent, ref } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { ROOT_STORE } from '@/store/constants'
|
||||
import { GeoJSONData } from '@/types/geojson'
|
||||
import { IWorkoutState } from '@/types/workouts'
|
||||
import { IWorkoutState, TCoordinates } from '@/types/workouts'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { getApiUrl } from '@/utils'
|
||||
|
||||
@ -40,12 +44,17 @@
|
||||
components: {
|
||||
LGeoJson,
|
||||
LMap,
|
||||
LMarker,
|
||||
LTileLayer,
|
||||
},
|
||||
props: {
|
||||
workout: {
|
||||
type: Object as PropType<IWorkoutState>,
|
||||
},
|
||||
markerCoordinates: {
|
||||
type: Object as PropType<TCoordinates>,
|
||||
required: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const { t } = useI18n()
|
||||
|
@ -53,7 +53,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<template #content>
|
||||
<WorkoutMap :workout="workout" />
|
||||
<WorkoutMap :workout="workout" :markerCoordinates="markerCoordinates" />
|
||||
<WorkoutData :workout="workout.workout" />
|
||||
</template>
|
||||
</Card>
|
||||
@ -71,7 +71,7 @@
|
||||
import { WORKOUTS_STORE } from '@/store/constants'
|
||||
import { ISport } from '@/types/sports'
|
||||
import { IAuthUserProfile } from '@/types/user'
|
||||
import { IWorkoutState } from '@/types/workouts'
|
||||
import { IWorkoutState, TCoordinates } from '@/types/workouts'
|
||||
import { useStore } from '@/use/useStore'
|
||||
import { formatWorkoutDate, getDateWithTZ } from '@/utils/dates'
|
||||
|
||||
@ -87,6 +87,10 @@
|
||||
type: Object as PropType<IAuthUserProfile>,
|
||||
required: true,
|
||||
},
|
||||
markerCoordinates: {
|
||||
type: Object as PropType<TCoordinates>,
|
||||
required: false,
|
||||
},
|
||||
sports: {
|
||||
type: Object as PropType<ISport[]>,
|
||||
},
|
||||
|
Reference in New Issue
Block a user