倒叙日历:
<template>
<div class="date-picker">
<div class="column" @wheel="onYearScroll">
<div v-for="(year, index) in displayedYears" :key="index" :class="{current: year === currentYear.value && index === 1}">
{{ year }}
</div>
</div>
<div class="column" @wheel="onMonthScroll">
<div v-for="(month, index) in displayedMonths" :key="index" :class="{current: month === currentMonth.value && index === 1}">
{{ monthString(month) }}
</div>
</div>
<div class="column" @wheel="onDayScroll">
<div v-for="(day, index) in displayedDays" :key="index" :class="{current: day === currentDay.value && index === 1}">
{{ dayString(day) }}
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const currentYear = ref(new Date().getFullYear())
const currentMonth = ref(new Date().getMonth() + 1)
const currentDay = ref(new Date().getDate())
const displayedYears = computed(() => {
const year = currentYear.value
return [year + 1, year, year - 1, year - 2]
})
const displayedMonths = computed(() => {
const month = currentMonth.value
return [
(month + 1 - 1) % 12 + 1,
month,
(month - 1 + 12) % 12 || 12,
(month - 2 + 12) % 12 || 12,
]
})
const daysInMonth = (year, month) => {
return new Date(year, month, 0).getDate()
}
const displayedDays = computed(() => {
const year = currentYear.value
const month = currentMonth.value
const day = currentDay.value
const daysInCurrentMonth = daysInMonth(year, month)
return [
(day + 1 - 1) % daysInCurrentMonth + 1,
day,
(day - 1 + daysInCurrentMonth - 1) % daysInCurrentMonth + 1,
(day - 2 + daysInCurrentMonth - 1) % daysInCurrentMonth + 1
]
})
const onYearScroll = (event) => {
event.preventDefault()
if (event.deltaY < 0) {
currentYear.value += 1
} else {
currentYear.value -= 1
}
// Reset month and day to 1
currentMonth.value = 1
currentDay.value = 1
}
const onMonthScroll = (event) => {
event.preventDefault()
if (event.deltaY < 0) {
currentMonth.value = (currentMonth.value % 12) + 1
} else {
currentMonth.value = (currentMonth.value - 1 + 11) % 12 + 1
}
// Reset day to 1
currentDay.value = 1
}
const onDayScroll = (event) => {
event.preventDefault()
const year = currentYear.value
const month = currentMonth.value
const daysInCurrentMonth = daysInMonth(year, month)
if (event.deltaY < 0) {
currentDay.value = (currentDay.value % daysInCurrentMonth) + 1
} else {
currentDay.value = (currentDay.value - 1 + daysInCurrentMonth - 1) % daysInCurrentMonth + 1
}
}
const monthString = (month) => {
return month.toString().padStart(2, '0')
}
const dayString = (day) => {
return day.toString().padStart(2, '0')
}
</script>
<style>
.date-picker {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
color: #fff !important;
}
.column {
display: flex;
flex-direction: column;
align-items: center;
width: 60px;
}
.column div {
height: 30px;
display: flex;
justify-content: center;
align-items: center;
}
.current {
font-weight: bold;
color: red;
}
</style>
正序日历:
<template>
<div class="date-picker">
<div class="column" @wheel="onYearScroll">
<div v-for="(year, index) in displayedYears" :key="index" :class="{current: year === currentYear}">
{{ year }}
</div>
</div>
<div class="column" @wheel="onMonthScroll">
<div v-for="(month, index) in displayedMonths" :key="index" :class="{current: month === currentMonth}">
{{ monthString(month) }}
</div>
</div>
<div class="column" @wheel="onDayScroll">
<div v-for="(day, index) in displayedDays" :key="index" :class="{current: day === currentDay}">
{{ dayString(day) }}
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const currentYear = ref(new Date().getFullYear())
const currentMonth = ref(new Date().getMonth() + 1)
const currentDay = ref(new Date().getDate())
const displayedYears = computed(() => {
const year = currentYear.value
return [year - 2, year - 1, year, year + 1, year + 2]
})
const displayedMonths = computed(() => {
const month = currentMonth.value
return [
(month - 2 + 12) % 12 || 12,
(month - 1 + 12) % 12 || 12,
month,
(month + 1 - 1) % 12 + 1,
(month + 2 - 1) % 12 + 1
]
})
const daysInMonth = (year, month) => {
return new Date(year, month, 0).getDate()
}
const displayedDays = computed(() => {
const year = currentYear.value
const month = currentMonth.value
const day = currentDay.value
const daysInCurrentMonth = daysInMonth(year, month)
return [
(day - 2 + daysInCurrentMonth) % daysInCurrentMonth || daysInCurrentMonth,
(day - 1 + daysInCurrentMonth) % daysInCurrentMonth || daysInCurrentMonth,
day,
(day + 1 - 1) % daysInCurrentMonth + 1,
(day + 2 - 1) % daysInCurrentMonth + 1
]
})
const onYearScroll = (event) => {
event.preventDefault()
if (event.deltaY > 0) {
currentYear.value += 1
} else {
currentYear.value -= 1
}
// Reset month and day to 1
currentMonth.value = 1
currentDay.value = 1
}
const onMonthScroll = (event) => {
event.preventDefault()
if (event.deltaY > 0) {
currentMonth.value = (currentMonth.value % 12) + 1
} else {
currentMonth.value = (currentMonth.value - 1 + 11) % 12 + 1
}
// Reset day to 1
currentDay.value = 1
}
const onDayScroll = (event) => {
event.preventDefault()
const year = currentYear.value
const month = currentMonth.value
const daysInCurrentMonth = daysInMonth(year, month)
if (event.deltaY > 0) {
currentDay.value = (currentDay.value % daysInCurrentMonth) + 1
} else {
currentDay.value = (currentDay.value - 1 + daysInCurrentMonth - 1) % daysInCurrentMonth + 1
}
}
const monthString = (month) => {
return month.toString().padStart(2, '0')
}
const dayString = (day) => {
return day.toString().padStart(2, '0')
}
</script>
<style>
.date-picker {
display: flex;
justify-content: center;
align-items: center;
gap: 20px;
color: #fff !important;
}
.column {
display: flex;
flex-direction: column;
align-items: center;
width: 60px;
}
.column div {
height: 30px;
display: flex;
justify-content: center;
align-items: center;
}
.current {
font-weight: bold;
color: red;
}
</style>