Client - add a fullscreen control to workout map - fix #140
This commit is contained in:
@ -23,6 +23,7 @@
|
||||
"register-service-worker": "^1.7.1",
|
||||
"vue": "^3.0.0",
|
||||
"vue-chart-3": "^3.0.7",
|
||||
"vue-fullscreen": "^3.1.1",
|
||||
"vue-i18n": "^9.1.9",
|
||||
"vue-router": "^4.0.0-0",
|
||||
"vuex": "^4.0.0-0"
|
||||
|
@ -2,47 +2,65 @@
|
||||
<div id="workout-map">
|
||||
<div v-if="workoutData.loading" class="leaflet-container" />
|
||||
<div v-else>
|
||||
<div class="leaflet-container" v-if="workoutData.workout.with_gpx">
|
||||
<LMap
|
||||
v-if="geoJson.jsonData && center && bounds.length === 2"
|
||||
:zoom="13"
|
||||
:maxZoom="19"
|
||||
:center="center"
|
||||
:bounds="bounds"
|
||||
ref="workoutMap"
|
||||
@ready="fitBounds(bounds)"
|
||||
<VFullscreen v-if="workoutData.workout.with_gpx" v-model="isFullscreen">
|
||||
<div
|
||||
class="leaflet-container"
|
||||
:class="{ 'fullscreen-map': isFullscreen }"
|
||||
>
|
||||
<LControlLayers />
|
||||
<LControl position="topleft" class="reset-button" @click="resetZoom">
|
||||
<i class="fa fa-refresh" aria-hidden="true"></i>
|
||||
</LControl>
|
||||
<LTileLayer
|
||||
:url="`${getApiUrl()}workouts/map_tile/{s}/{z}/{x}/{y}.png`"
|
||||
:attribution="appConfig.map_attribution"
|
||||
<LMap
|
||||
v-if="geoJson.jsonData && center && bounds.length === 2"
|
||||
:zoom="13"
|
||||
:maxZoom="19"
|
||||
:center="center"
|
||||
:bounds="bounds"
|
||||
/>
|
||||
<LGeoJson :geojson="geoJson.jsonData" />
|
||||
<LMarker
|
||||
v-if="markerCoordinates.latitude"
|
||||
:lat-lng="[markerCoordinates.latitude, markerCoordinates.longitude]"
|
||||
/>
|
||||
<LLayerGroup
|
||||
:name="$t('workouts.START_AND_FINISH')"
|
||||
layer-type="overlay"
|
||||
ref="workoutMap"
|
||||
@ready="fitBounds(bounds)"
|
||||
>
|
||||
<CustomMarker
|
||||
v-if="startMarkerCoordinates.latitude"
|
||||
:markerCoordinates="startMarkerCoordinates"
|
||||
:isStart="true"
|
||||
<LControlLayers />
|
||||
<LControl position="topleft" class="map-control" @click="resetZoom">
|
||||
<i class="fa fa-refresh" aria-hidden="true" />
|
||||
</LControl>
|
||||
<LControl
|
||||
position="topleft"
|
||||
class="map-control"
|
||||
@click="toggleFullscreen"
|
||||
>
|
||||
<i
|
||||
:class="`fa fa-${isFullscreen ? 'compress' : 'arrows-alt'}`"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</LControl>
|
||||
<LTileLayer
|
||||
:url="`${getApiUrl()}workouts/map_tile/{s}/{z}/{x}/{y}.png`"
|
||||
:attribution="appConfig.map_attribution"
|
||||
:bounds="bounds"
|
||||
/>
|
||||
<CustomMarker
|
||||
v-if="endMarkerCoordinates.latitude"
|
||||
:markerCoordinates="endMarkerCoordinates"
|
||||
:isStart="false"
|
||||
<LGeoJson :geojson="geoJson.jsonData" />
|
||||
<LMarker
|
||||
v-if="markerCoordinates.latitude"
|
||||
:lat-lng="[
|
||||
markerCoordinates.latitude,
|
||||
markerCoordinates.longitude,
|
||||
]"
|
||||
/>
|
||||
</LLayerGroup>
|
||||
</LMap>
|
||||
</div>
|
||||
<LLayerGroup
|
||||
:name="$t('workouts.START_AND_FINISH')"
|
||||
layer-type="overlay"
|
||||
>
|
||||
<CustomMarker
|
||||
v-if="startMarkerCoordinates.latitude"
|
||||
:markerCoordinates="startMarkerCoordinates"
|
||||
:isStart="true"
|
||||
/>
|
||||
<CustomMarker
|
||||
v-if="endMarkerCoordinates.latitude"
|
||||
:markerCoordinates="endMarkerCoordinates"
|
||||
:isStart="false"
|
||||
/>
|
||||
</LLayerGroup>
|
||||
</LMap>
|
||||
</div>
|
||||
</VFullscreen>
|
||||
<div v-else class="no-map">{{ $t('workouts.NO_MAP') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -114,6 +132,7 @@
|
||||
}
|
||||
: {}
|
||||
)
|
||||
const isFullscreen = ref(false)
|
||||
|
||||
function getGeoJson(gpxContent: string): GeoJSONData {
|
||||
if (!gpxContent || gpxContent !== '') {
|
||||
@ -157,6 +176,14 @@
|
||||
function resetZoom() {
|
||||
workoutMap.value?.leafletObject.fitBounds(getBounds())
|
||||
}
|
||||
function toggleFullscreen() {
|
||||
isFullscreen.value = !isFullscreen.value
|
||||
if (!isFullscreen.value) {
|
||||
setTimeout(() => {
|
||||
resetZoom()
|
||||
}, 100)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@ -171,13 +198,21 @@
|
||||
.no-map {
|
||||
line-height: 400px;
|
||||
}
|
||||
.reset-button {
|
||||
.map-control {
|
||||
background: #ffffff;
|
||||
padding: 5px 10px;
|
||||
border: 2px solid #bfc0ab;
|
||||
border-radius: 3px;
|
||||
color: #000000;
|
||||
}
|
||||
::v-deep(.fullscreen) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.fullscreen-map {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $small-limit) {
|
||||
padding: 0;
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
} from 'chart.js'
|
||||
import ChartDataLabels from 'chartjs-plugin-datalabels'
|
||||
import { createApp } from 'vue'
|
||||
import VueFullscreen from 'vue-fullscreen'
|
||||
|
||||
import './registerServiceWorker'
|
||||
import App from './App.vue'
|
||||
@ -45,6 +46,7 @@ const app = createApp(App)
|
||||
.use(i18n)
|
||||
.use(store)
|
||||
.use(router)
|
||||
.use(VueFullscreen, { name: 'VFullscreen' })
|
||||
.directive('click-outside', clickOutsideDirective)
|
||||
|
||||
customComponents.forEach((component) => {
|
||||
|
@ -8501,6 +8501,11 @@ schema-utils@^3.0.0:
|
||||
ajv "^6.12.5"
|
||||
ajv-keywords "^3.5.2"
|
||||
|
||||
screenfull@^5.1.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/screenfull/-/screenfull-5.2.0.tgz#6533d524d30621fc1283b9692146f3f13a93d1ba"
|
||||
integrity sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==
|
||||
|
||||
select-hose@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
|
||||
@ -9773,6 +9778,13 @@ vue-eslint-parser@^7.0.0, vue-eslint-parser@^7.10.0:
|
||||
lodash "^4.17.21"
|
||||
semver "^6.3.0"
|
||||
|
||||
vue-fullscreen@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/vue-fullscreen/-/vue-fullscreen-3.1.1.tgz#385097e0b43f4604ded99adb0ceb225dea3e0326"
|
||||
integrity sha512-I59sIO0O22116gwVPo1qM2cNf5binEC5vTswIm8qJsqgatGfFquIJANpoVggSUS2EgUF0Xg4tHliT1ITcwQw8Q==
|
||||
dependencies:
|
||||
screenfull "^5.1.0"
|
||||
|
||||
vue-hot-reload-api@^2.3.0:
|
||||
version "2.3.4"
|
||||
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"
|
||||
|
Reference in New Issue
Block a user