本組件分紅兩個組件,一個是單獨的一個反轉的數字,另外一個是把這個翻頁組成一個計時器。css
countTurn.vue
<template>
<div id="stage-1" class="stage stage-state-default">
<div class="stage-content">
<ul class="stage-1-icon">
<li :class="'stage-1-icon-1'">
<div class="stage-1-icon-top" :class="change?'turn-top':''" :style="{backgroundImage:'url('+pic1+')'}">
</div>
<div class="stage-1-icon-bottom" :style="{backgroundImage:'url('+pic1+')'}">
</div>
</li>
<li :class="'stage-1-icon-2'">
<div class="stage-1-icon-top" :style="{backgroundImage:'url('+pic2+')'}">
</div>
<div class="stage-1-icon-bottom" :class="change?'turn-bottom':''" :style="{backgroundImage:'url('+pic2+')'}">
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
import pic1 from '../../assets/count/1.png'//圖片素材
import pic2 from '../../assets/count/2.png'
import pic3 from '../../assets/count/3.png'
import pic4 from '../../assets/count/4.png'
import pic5 from '../../assets/count/5.png'
import pic6 from '../../assets/count/6.png'
import pic7 from '../../assets/count/7.png'
import pic8 from '../../assets/count/8.png'
import pic9 from '../../assets/count/9.png'
import pic0 from '../../assets/count/0.png'
const picList = [pic0, pic1, pic2, pic3, pic4, pic5, pic6, pic7, pic8, pic9]
export default {
props: ['num'],
data() {
return {
change: false,
pic1: pic1,
pic2: pic2,
}
},
watch: {
num(newVal, oldVal) { // 當數據改變時觸發動畫
this.pic1 = picList[oldVal]
this.pic2 = picList[newVal]
this.change = false
setTimeout(() => {
this.change = true
}, 100)
},
},
mounted() {
if (this.num) {// 數字初始化爲0
;(this.pic1 = picList[this.num]), (this.pic2 = pic1[this.num + 1 == 10 ? 0 : this.num])
} else {
;(this.pic1 = pic0), (this.pic2 = pic1)
}
},
}
</script>
<style lang="less" scoped>
ol,
ul {
list-style: none;
}
#stage-1 .stage-content {
margin: auto 0 auto;
}
.stage-1-icon {
width: 20px; // 圖片寬度
height: 37px; // 圖片高度
margin: 0 auto 0;
position: relative;
-webkit-perspective: 900px;
}
.stage-1-icon-top,
.stage-1-icon-bottom {
width: 20px; // 圖片寬度
position: absolute;
left: 0;
background-color: #0342aa;// 背景色
background-repeat: no-repeat;
-webkit-transform-style: preserve-3d;
}
.stage-1-icon-top {
height: 18px; //上半截的高度
padding: 0;
top: 0;
background-position: center 0;
-webkit-transform-origin: center bottom;
-moz-transform-origin: center bottom;
-ms-transform-origin: center bottom;
-o-transform-origin: center bottom;
transform-origin: center bottom;// 作-webkit-、-moz-、-ms-、-o-兼容
}
.stage-1-icon-bottom {
height: 18px; // 下半截的高度
top: 18px; // 下半截的位移高度
// padding: 0 10px 10px;
background-position: center -18px; // 下半截的背景圖位移高度
// ……,作-webkit-、-moz-、-ms-、-o-兼容
transform-origin: center top;
}
.stage-1-icon-1 .stage-1-icon-top,
.stage-1-icon-1 .stage-1-icon-bottom {
z-index: 6; // 初始化更小數字的圖片在上面
background-size: 100% 200%;
}
.stage-1-icon-2 .stage-1-icon-top,
.stage-1-icon-2 .stage-1-icon-bottom {
z-index: 5; // 初始化更大數字的圖片在下面
background-size: 100% 200%;
}
@-webkit-keyframes flipover-top {
0% {
z-index: 8;// 這是數字上半塊的z-index
background-color: #0342aa;
-webkit-transform: rotateX(0);
}
50% {
z-index: 8;
background-color: rgba(0, 0, 0, 0.1);
-webkit-transform: rotateX(-90deg);
}
50.1% {
z-index: 7;// 注意z-index的改變
opacity: 1;
}
100% {
z-index: 7;
background-color: #0342aa;
opacity: 0;// 結束時直接透明啦
-webkit-transform: rotateX(-180deg);
}
}
@-moz-keyframes flipover-top {
……
}
@-ms-keyframes flipover-top {
……
}
@-o-keyframes flipover-top {
……
}
@keyframes flipover-top {
……
}
@-webkit-keyframes flipover-bottom {
0% {
z-index: 7;
background-color: #0342aa;
-webkit-transform: rotateX(180deg);
}
50% {
z-index: 7;
background-color: rgba(0, 0, 0, 0.1);
-webkit-transform: rotateX(90deg);
}
50.1% {
z-index: 8;
}
100% {
z-index: 6;// 結束時把它調整爲數字較少圖的那一層,看.stage-1-icon-1 .stage-1-icon-top的z-index
background-color: #0342aa;
-webkit-transform: rotateX(0);
}
}
@-moz-keyframes flipover-bottom {
……
}
@-ms-keyframes flipover-bottom {
……
}
@-o-keyframes flipover-bottom {
……
}
@keyframes flipover-bottom {
……
}
#stage-1.stage-state-default {
z-index: 1;
}
.turn-top { // 上半塊動畫
// ……,作-webkit-、-moz-、-ms-、-o-兼容
animation: flipover-top 0.15s linear 0s 1 normal forwards;
}
.turn-bottom { // 下半塊動畫
// ……,作-webkit-、-moz-、-ms-、-o-兼容
animation: flipover-bottom 0.15s linear 0s 1 normal forwards;
}
</style>
複製代碼
(兼容性的代碼太長註釋掉了 自行加上哈)html
上面注意的知識點有如下幾點:vue
一張圖片,經過background-image引入,並且分紅上下兩塊。web
<div class="stage-1-icon-top" :class="change?'turn-top':''" :style="{backgroundImage:'url('+pic1+')'}"></div>
<div class="stage-1-icon-bottom" :style="{backgroundImage:'url('+pic1+')'}"></div>
複製代碼
2.用change屬性從新觸發動畫 html:bash
<div class="stage-1-icon-top" :class="change?'turn-top':''" :style="{backgroundImage:'url('+pic1+')'}"></div>
……
<div class="stage-1-icon-bottom" :class="change?'turn-bottom':''" :style="{backgroundImage:'url('+pic2+')'}">
複製代碼
js:
less
num(newVal, oldVal) {
this.pic1 = picList[oldVal]
this.pic2 = picList[newVal]
this.change = false // 改爲false
setTimeout(() => {
this.change = true // 過零點一毫秒再改成true
}, 100)
},
複製代碼
css:函數
.turn-top { // 上半塊動畫
// ……,作-webkit-、-moz-、-ms-、-o-兼容
animation: flipover-top 0.15s linear 0s 1 normal forwards;
}
.turn-bottom { // 下半塊動畫
// ……,作-webkit-、-moz-、-ms-、-o-兼容
animation: flipover-bottom 0.15s linear 0s 1 normal forwards;
}
複製代碼
每一個寫有z-index的地方都要留意,由於是關鍵鴨!性能
timer.vueflex
<template>
<div class="timer">
<countTurn :num="hh"></countTurn>
<countTurn :num="h"></countTurn>
<img src="../../assets/count/_.png" class="img" alt=":">
<countTurn :num="mm"></countTurn>
<countTurn :num="m"></countTurn>
<img src="../../assets/count/_.png" class="img" alt=":">
<countTurn :num="ss"></countTurn>
<countTurn :num="s"></countTurn>
</div>
</template>
<script>
import countTurn from '../countTurn' //子組件引入
let timer = null
export default {
components: {countTurn},
data() {
return {
hh: 0,
h: 0,
mm: 0,
m: 0,
ss: 0,
s: 0,
}
},
mounted() {
this.startTimer(new Date())
setInterval(() => {
this.startTimer(new Date())
}, 1000 * 60 * 60) // 一小時跟進一下實際時間防止系統卡頓產生計時偏差
},
methods: {
startTimer(date) {
if (timer) {
clearInterval(timer)
}
let dt = new Date(date)
// 初始化6個值
this.hh = dt.getHours() >= 10 ? Math.floor(dt.getHours() / 10) : 0
this.h = dt.getHours() % 10
this.mm = dt.getMinutes() >= 10 ? Math.floor(dt.getMinutes() / 10) : 0
this.m = dt.getMinutes() % 10
this.ss = dt.getSeconds() >= 10 ? Math.floor(dt.getSeconds() / 10) : 0
this.s = dt.getSeconds() % 10
// 開始計時
timer = setInterval(() => {
this.s++
if (this.s == 10) {
this.s = 0
this.ss++
if (this.ss == 6) {
this.ss = 0
this.m++
if (this.m == 10) {
this.m = 0
this.mm++
if (this.mm == 6) {
this.mm = 0
this.h++
if (this.hh * 10 + this.h == 24) {
this.hh = 0
this.h = 0
} else if (this.h == 10) {
this.h = 0
this.hh++
}
}
}
}
}
}, 1000)
},
},
}
</script>
<style lang="less" scoped>
.timer {
display: flex;
align-items: center;
justify-content: center;
}
.img{
width: 10px;
}
</style>
複製代碼
這一塊代碼主要重點在於計時的函數startTimer() 動畫
1.使用setInterval()1秒循環一次
2.一小時跟進一下實際時間防止系統卡頓產生計時偏差再調用一次startTime(),因此在函數開始時先清一下以前的計時器clearInterval(timer),而後再從新獲取一次時間。
3.爲何這裏不直接每一秒都獲取一下時間呢?
每秒都拿一次會影響性能 大體分享到這裏,圖片使用本身的圖片替代就能夠啦~
ps: 第一次寫掘金的文章,有什麼不足請多多指點。