时钟翻牌器 vue3

作者 : admin 本文共5571个字,预计阅读时间需要14分钟 发布时间: 2024-06-6 共2人阅读

时钟翻牌器 vue3插图

时钟翻牌器 vue3插图(1)

index.vue

<template>
<div class="FlipClock">
<Flipper ref="flipperHour" />
<em>:</em>
<Flipper ref="flipperMinute" />
<em>:</em>
<Flipper ref="flipperSecond" />
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue"
import Flipper from "./Flipper.vue"
const timer = ref<any>(null)
const flipObjs = ref<any[]>([])
const flipperHour = ref()
const flipperMinute = ref()
const flipperSecond = ref()
// 初始化数字
function init() {
let now = new Date()
let nowTimeStr = formatDate(new Date(now.getTime()), "hh-ii-ss")
nowTimeStr = nowTimeStr.split("-")
for (let i = 0; i < flipObjs.value.length; i++) {
flipObjs.value[i].value.setFront(nowTimeStr[i])
}
}
// 开始计时
function run() {
timer.value = setInterval(() => {
// 获取当前时间
let now = new Date()
let nowTimeStr = formatDate(new Date(now.getTime() - 1000), "hh-ii-ss")
nowTimeStr = nowTimeStr.split("-")
let nextTimeStr = formatDate(now, "hh-ii-ss")
nextTimeStr = nextTimeStr.split("-")
for (let i = 0; i < flipObjs.value.length; i++) {
if (nowTimeStr[i] === nextTimeStr[i]) {
continue
}
flipObjs.value[i].value.flipDown(nowTimeStr[i], nextTimeStr[i])
}
}, 1000)
}
// 正则格式化日期
function formatDate(date, dateFormat) {
/* 单独格式化年份,根据y的字符数量输出年份
* 例如:yyyy => 2019
yy => 19
y => 9
*/
if (/(y+)/.test(dateFormat)) {
dateFormat = dateFormat.replace(
RegExp.$1,
(date.getFullYear() + "").substr(4 - RegExp.$1.length)
)
}
// 格式化月、日、时、分、秒
let o = {
"m+": date.getMonth() + 1,
"d+": date.getDate(),
"h+": date.getHours(),
"i+": date.getMinutes(),
"s+": date.getSeconds()
}
for (let k in o) {
if (new RegExp(`(${k})`).test(dateFormat)) {
// 取出对应的值
let str = o[k] + ""
/* 根据设置的格式,输出对应的字符
* 例如: 早上8时,hh => 08,h => 8
* 但是,当数字>=10时,无论格式为一位还是多位,不做截取,这是与年份格式化不一致的地方
* 例如: 下午15时,hh => 15, h => 15
*/
dateFormat = dateFormat.replace(RegExp.$1, RegExp.$1.length === 1 ? str : padLeftZero(str))
}
}
return dateFormat
}
// 日期时间补零
function padLeftZero(str) {
return str.toString().padStart(2, "0")
}
onMounted(() => {
flipObjs.value = [flipperHour, flipperMinute, flipperSecond]
init()
run()
})
</script>
<style lang="scss" scoped>
.FlipClock {
text-align: center;
}
.FlipClock .M-Flipper {
margin: 0 3px;
}
.FlipClock em {
display: inline-block;
line-height: 102px;
font-size: 66px;
font-style: normal;
vertical-align: top;
}
</style>

Flipper.vue

<template>
<div class="M-Flipper" :class="[flipType, { go: isFlipping }]">
<div class="digital front" :class="_textClass(frontTextFromData)"></div>
<div class="digital back" :class="_textClass(backTextFromData)"></div>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue"
const props = defineProps({
// front paper text
// 前牌文字
frontText: {
type: [Number, String],
default: "00"
},
// back paper text
// 后牌文字
backText: {
type: [Number, String],
default: "01"
},
// flipping duration, please be consistent with the CSS animation-duration value.
// 翻牌动画时间,与CSS中设置的animation-duration保持一致
duration: {
type: Number,
default: 600
}
})
const isFlipping = ref(false)
const flipType = ref("down")
const frontTextFromData = ref(props.frontText)
const backTextFromData = ref(props.backText)
function _textClass(number) {
return "number" + number
}
function _flip(type, front, back) {
// 如果处于翻转中,则不执行
if (isFlipping.value) {
return false
}
frontTextFromData.value = front
backTextFromData.value = back
// 根据传递过来的type设置翻转方向
flipType.value = type
// 设置翻转状态为true
isFlipping.value = true
setTimeout(() => {
// 设置翻转状态为false
isFlipping.value = false
frontTextFromData.value = back
}, props.duration)
}
// 下翻牌
function flipDown(front, back) {
_flip("down", front, back)
}
// 上翻牌
function flipUp(front, back) {
_flip("up", front, back)
}
// 设置前牌文字
function setFront(text) {
frontTextFromData.value = text
}
// 设置后牌文字
function setBack(text) {
backTextFromData.value = text
}
defineExpose({
flipDown,
flipUp,
setFront,
setBack
})
</script>
<style lang="scss" scoped>
.M-Flipper {
display: inline-block;
position: relative;
width: 120px;
height: 100px;
line-height: 100px;
border: solid 1px #000;
border-radius: 10px;
background: #fff;
font-size: 66px;
color: #fff;
box-shadow: 0 0 6px rgba(0, 0, 0, 0.5);
text-align: center;
font-family: "Helvetica Neue";
}
.M-Flipper .digital:before,
.M-Flipper .digital:after {
content: "";
position: absolute;
left: 0;
right: 0;
background: #000;
overflow: hidden;
box-sizing: border-box;
}
.M-Flipper .digital:before {
top: 0;
bottom: 50%;
border-radius: 10px 10px 0 0;
border-bottom: solid 1px #666;
}
.M-Flipper .digital:after {
top: 50%;
bottom: 0;
border-radius: 0 0 10px 10px;
line-height: 0;
}
/*向下翻*/
.M-Flipper.down .front:before {
z-index: 3;
}
.M-Flipper.down .back:after {
z-index: 2;
transform-origin: 50% 0%;
transform: perspective(160px) rotateX(180deg);
}
.M-Flipper.down .front:after,
.M-Flipper.down .back:before {
z-index: 1;
}
.M-Flipper.down.go .front:before {
transform-origin: 50% 100%;
animation: frontFlipDown 0.6s ease-in-out both;
box-shadow: 0 -2px 6px rgba(255, 255, 255, 0.3);
backface-visibility: hidden;
}
.M-Flipper.down.go .back:after {
animation: backFlipDown 0.6s ease-in-out both;
}
/*向上翻*/
.M-Flipper.up .front:after {
z-index: 3;
}
.M-Flipper.up .back:before {
z-index: 2;
transform-origin: 50% 100%;
transform: perspective(160px) rotateX(-180deg);
}
.M-Flipper.up .front:before,
.M-Flipper.up .back:after {
z-index: 1;
}
.M-Flipper.up.go .front:after {
transform-origin: 50% 0;
animation: frontFlipUp 0.6s ease-in-out both;
box-shadow: 0 2px 6px rgba(255, 255, 255, 0.3);
backface-visibility: hidden;
}
.M-Flipper.up.go .back:before {
animation: backFlipUp 0.6s ease-in-out both;
}
@keyframes frontFlipDown {
0% {
transform: perspective(160px) rotateX(0deg);
}
100% {
transform: perspective(160px) rotateX(-180deg);
}
}
@keyframes backFlipDown {
0% {
transform: perspective(160px) rotateX(180deg);
}
100% {
transform: perspective(160px) rotateX(0deg);
}
}
@keyframes frontFlipUp {
0% {
transform: perspective(160px) rotateX(0deg);
}
100% {
transform: perspective(160px) rotateX(180deg);
}
}
@keyframes backFlipUp {
0% {
transform: perspective(160px) rotateX(-180deg);
}
100% {
transform: perspective(160px) rotateX(0deg);
}
}
.M-Flipper {
@for $i from 0 through 59 {
$classPrefix: if($i <= 9, "number0", "number");
$content: if($i <= 9, "0" + $i, $i);
.digital.#{$classPrefix}#{$i}:before,
.digital.#{$classPrefix}#{$i}:after {
// 你的样式
content: "#{$content}";
}
}
}
</style>

感谢大神_Nealyang_博客
感谢大神_Nealyang_Github

本站无任何商业行为
个人在线分享 » 时钟翻牌器 vue3
E-->