<template>
<view class="content" style="margin: 20px auto 40px auto;">
<view class="flip-container">
<view class="flip-items" v-for="(unit,unitIndex) of timeArr" :key="unitIndex">
<view class="item" v-for="(item,index) of unit.max + 1" :key="index"
:class="{current: unit.current == index, past: unit.current + 1 == index || index==unit.max&&unit.current==0}">
<view class="up">
<view class="inner">{{index}}</view>
<view class="shadow"></view>
</view>
<view class="down">
<view class="inner">{{index}}</view>
<view class="shadow"></view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
props: ['residue_time'],
data() {
return {
timeStr: '',
residueTime: '',
timer: null
}
},
computed: {
timeArr() {
let timeFormat= [...this.timeStr].map((unit, index) => {
let max;
if (3==index || 5 ==index) { //分秒的个位
max = 9
} else if (index == 0) { //时十位
max = 2
}else if (index == 1) { //时个位
max = 3
} else if (index == 2 || index == 4) { //分秒的十位
max = 5
}
return {
max,
current: Number(unit),
}
})
return timeFormat
}
},
methods: {
init(residue_time) {
this.residueTime = residue_time
this.countDown();
if(this.residueTime>0){
this.timer = setInterval(() => {
if(0>Number(this.residueTime)){
this.clearTimer();
// 倒计时结束处理
this.$emit('timeup')
}
this.countDown();
}, 1000)
}
},
countDown() {
const {
h,
i,
s
} = this.secondsFormat(this.residueTime)
this.timeStr = h + i + s;
this.residueTime--
},
secondsFormat(seconds) {
let [day, hour, minute, second] = [0, 0, 0, 0]
if (seconds > 0) {
day = Math.floor(seconds / (60 * 60 * 24))
hour = Math.floor(seconds / (60 * 60)) - (day * 24)
minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
}
if (day < 10) {
day = '0' + day
}
if (hour < 10) {
hour = '0' + hour
}
if (minute < 10) {
minute = '0' + minute
}
if (second < 10) {
second = '0' + second
}
return {
d: day,
h: hour,
i: minute,
s: second
};
},
clearTimer(){
clearInterval(this.timer)
this.timer=null;
}
},
};
</script>
<style lang="stylus">
$width = 100rpx;
$time = 1s
$height = $width * 1.5;
$lineWidth = ($width / 60);
$radius = ($width / 10);
$perspective = $width * 5;
$gap= $width * 0.2
.flip-container
display flex
justify-content center
padding 0 20rpx
position relative
.flip-items
position relative
width $width
height $height
font-size 60rpx
font-weight bold
border-radius $radius
box-shadow: 0 2rpx 18rpx rgba(0, 0, 0, 0.7)
&:nth-of-type(2n+1)
margin-right 10rpx
&:nth-of-type(2),&:nth-of-type(4)
margin-right 50rpx
&::after,&::before
position absolute
right -(@margin-right / 2)
content ''
transform translateX(50%)
width 12rpx
height @width
border-radius 50%
background-color #E22A2A
&::before
top 35%
&::after
bottom 35%
.item
z-index 1
position absolute
top 0
left 0
right 0
bottom 0
perspective $perspective
&:before
content: ''
position absolute
top (($height - $lineWidth) / 2)
left 0
z-index 9
width: 100%
height: $lineWidth
min-height 2px
background-color rgba(0, 0, 0, 0.6)
.up,.down
position absolute;
left 0;
right 0
height 50%;
overflow hidden
.up
transform-origin 50% 100%
top 0
.down
transform-origin 50% 0%
bottom 0
.inner
position: absolute;
left: 0;
width: 100%;
height: $height
line-height $height
color: #E22A2A;
font-size:50rpx;
text-shadow: 0 2rpx 4rpx #000
text-align: center;
background-color: #222
border-radius: $radius
.up .inner
top 0
.down .inner
bottom 0
.up .shadow
border-top-left-radius $radius
border-top-right-radius $radius
.down .shadow
border-bottom-left-radius $radius
border-bottom-right-radius $radius
.flip-items .item
&.past {
z-index: 3;
}
&.current {
//反转到中间时候当前秒层级最大
animation: highter-level ($time/2) ($time/2) linear forwards;
z-index: 2;
}
&.past .up {
animation: flip-past-up ($time/2) linear both;
}
&.current .down {
animation: flip-current-down ($time/2) ($time/2) linear both;
}
@keyframes flip-current-down {
from{
transform: rotateX(90deg);
}
to {
transform: rotateX(0deg);
}
}
@keyframes flip-past-up {
from{
transform: rotateX(0deg);
}
to {
transform: rotateX(-90deg);
}
}
@keyframes highter-level {
from{
z-index: 4;
}
to {
z-index: 4;
}
}
// 控制阴影
.flip-items .item
.shadow {
position: absolute;
width: 100%;
height: 100%;
}
&.past .up .shadow {
background: linear-gradient(rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 1) 100%);
animation: show ($time/2) linear both;
}
&.past .down .shadow {
background: linear-gradient(rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.1) 100%);
animation: show ($time/2) linear both;
}
&.current .up .shadow {
background: linear-gradient(rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 1) 100%);
animation: hide ($time/2) 0.3s linear both;
}
&.current .down .shadow {
background: linear-gradient(rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, 0.1) 100%);
animation: hide ($time/2) 0.3s linear both;
}
@keyframes show {
from{
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes hide {
from{
opacity: 1;
}
to {
opacity: 0;
}
}
</style>
效果图: