Implement day navigation gestures with Swiper.js

This commit is contained in:
2022-09-11 20:40:08 +02:00
parent 8d9bcee279
commit 4346aa23c5
19 changed files with 2966 additions and 2342 deletions

View File

@ -0,0 +1,112 @@
<script setup>
import { selectedDate, changeDate, changeDay } from "../store";
import { Swiper, SwiperSlide } from "swiper/vue";
import { Virtual } from "swiper";
import { ref, watch } from "vue";
defineProps({
element: {
required: true,
},
});
// Get swiper element
const swiperModules = ref([Virtual]);
const swiperElement = ref();
function setSwiper(swiper) {
swiperElement.value = swiper;
}
// Load current, previous and next day
const loadedDates = ref([
new Date(selectedDate.value.getTime() - 86400000),
new Date(selectedDate.value.getTime()),
new Date(selectedDate.value.getTime() + 86400000),
]);
// Load left or right date on slide change
function slideChange(swiper) {
selectedDate.value = loadedDates.value[swiper.activeIndex];
const activeSlide = swiper.activeIndex;
if (activeSlide == loadedDates.value.length - 1) {
const lastDate = loadedDates.value[loadedDates.value.length - 1];
loadedDates.value.push(calculateDate(lastDate, 1));
}
}
function slideChangeEnd(swiper) {
const activeSlide = swiper.activeIndex;
if (activeSlide == 0) {
const lastDate = loadedDates.value[0];
loadedDates.value = [calculateDate(lastDate, -1), ...loadedDates.value];
swiper.slideTo(activeSlide + 1, 0);
}
}
// Helper functions
function calculateDate(date, offset) {
return new Date(date.getTime() + 86400000 * offset);
}
function calculateSlide(date) {
return loadedDates.value.findIndex((e) => e.getTime() == date.getTime());
}
function slideToDate(date) {
const slide = calculateSlide(date);
if (slide != -1) swiperElement.value.slideTo(slide);
else {
loadedDates.value = [calculateDate(date, -1), date, calculateDate(date, 1)];
swiperElement.value.slideTo(1, 0);
}
selectedDate.value = date;
}
// Watch for slide change instructions
watch(changeDay, (change) => {
if (change == 0) return;
slideToDate(calculateDate(selectedDate.value, change));
changeDay.value = 0;
});
watch(changeDate, (date) => {
slideToDate(new Date(date.setUTCHours(0, 0, 0, 0)));
});
</script>
<template>
<swiper
:modules="swiperModules"
:slides-per-view="1"
:space-between="50"
:initial-slide="1"
:virtual="true"
@slide-change-transition-end="slideChangeEnd"
@slide-change="slideChange"
@swiper="setSwiper"
>
<swiper-slide
v-for="(date, index) in loadedDates"
:key="index"
:virtualIndex="index"
>
<div class="content">
<component :is="element" :date="date" />
</div>
</swiper-slide>
</swiper>
</template>
<style>
@import "swiper/css";
</style>
<style scoped>
.swiper {
padding: 10px;
z-index: 0;
height: 100%;
}
.content {
height: calc(100% - 100px);
overflow-y: auto;
padding-bottom: 100px;
}
</style>