動畫合成小技巧!CSS 實現動感的倒計時效果
介紹一個 CSS 動畫合成小技巧。先看效果
這是一個非常 “動感” 的倒計時效果,在一些活動開場中比較常見,分析一下整個動畫過程,不難發現,有以下幾類動畫
-
數字的變化
-
縮小和放大
-
透明度變化
不知道小夥伴能否觀察出來呢?下面來一起來看看具體實現吧
一、數字的變化
先來看數字的變化。
這個技巧在之前的文章:還在使用定時器嗎?CSS 也能實現電子時鐘 中首次用到,這裏再次介紹一下
在以前,數字的變化可能需要創建多個標籤,然後改變位移來實現
<count-down>
<span>5</span>
<span>4</span>
<span>3</span>
<span>2</span>
<span>1</span>
</count-down>
這種方式需要創建多個標籤,略微繁瑣,也不易擴展。現在有更簡潔的方式可以實現了,那就是 CSS @property[1]。這是幹什麼的呢?簡單來講,可以自定義屬性,在這個例子中,可以讓數字像顏色一樣進行過渡和動畫,可能不太懂,直接看例子吧
假設 HTML 是這樣的
<count-down style="--t: 5"></count-down>
然後我們通過 CSS 變量將數字渲染到頁面,這裏需要藉助僞元素和計數器
有興趣的可以參考這篇文章:小 tips: 如何藉助 content 屬性顯示 CSS var 變量值 [2]
count-down::after{
counter-reset: time var(--t);
content: counter(time);
}
效果如下
如何讓這個數字變化呢?可以用到 CSS 動畫
@keyframes count {
to {
--t: 0
}
}
count-down::after{
--t: 5;
counter-reset: time var(--t);
content: counter(time);
animation: count 5s forwards;
}
效果如下
現在的效果僅僅是 5 秒後,數字從 5 變成了 0,並沒有 5 => 4 => 3 => 2 => 1 這種階段變化。然後最重要的一步來了,加上以下自定義屬性
@property --t {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
對的,僅僅添加這一小段 CSS,效果就出來了
是不是很神奇?可以這麼理解,通過@property
定義後,這個變量--t
本身可以單獨設置動畫了,就像顏色變化一樣。
另外,使用計數器的好處是可以隨意更換類型,比如將上面的阿拉伯數字換成中文計數,只需要更換計數器類型就行了
完整類型可以參考:list-style-type[3]
count-down::after{
--t: 5;
counter-reset: time var(--t);
content: counter(time, cjk-decimal); /*中日韓十進制數*/
animation: count 5s forwards;
}
效果如下
是不是非常方便呢?
二、倒計時的終點
上面的計數器最後的終點是 “0”,顯然我們需要一些特定的提示,比如 “Go~”
如何改變最後一幀的狀態呢?這裏有兩種方式:
-
通過動畫覆蓋
-
通過計數器覆蓋
首先來看第一種方式,這個比較好理解,重新定義一個動畫,在倒計時結束後,將最後一幀重置一下
@keyframes stop {
to {
content: 'Go~';
}
}
count-down::after{
--t: 5;
counter-reset: time var(--t);
content: counter(time);
animation: count 5s forwards,
stop 5s step-end forwards;
}
· 效果如下
注意這裏動畫函數是step-end
,爲啥是這個呢?step-end
也可寫作steps(1,end)
,你可以理解爲在整個動畫只有兩種狀態,在運行過程中,都是初始狀態,只有到達最後一幀才改變狀態,下面是 MDN 的截圖
下面來看第二種方式,通過自定義計數器來實現。原理其實和 JS 思維有些類似,當數字爲 0 時,讓計數器指定一個特殊的值,具體實現如下
@counter-style stop {
system: cyclic;
symbols: "Go~";
range: 0 0;
}
這裏簡單解釋一下,這裏有個range
屬性,表示計數器的範圍,由於這裏只需要指定爲 0,所以是區間0 0
。然後是system
,表示計算系統,這裏爲cyclic
,表示循環使用開發者提供的一套字符,字符由symbos
定義。然後symbos
表示計算符號,也就是具體展示的字符,這裏指定爲Go~
就行了。
這部分自定義計數器內容比較複雜,也比較新,有興趣的可以參考張鑫旭的這篇文章:CSS @counter-style 規則詳細介紹 [4]
然後是應用
count-down::after{
/**/
counter-reset: time var(--t);
content: counter(time, stop); /*自定義計數器*/
}
這樣也能達到相同的效果,實現也更加優雅
三、縮放和透明度變化
這兩個動畫其實是同時進行的,可以放在一個動畫裏
@keyframes shark {
0%{
opacity: 1;
transform: scale(1);
}
50%{
opacity: 0;
transform: scale(0.4);
}
}
然後設置動畫時長爲 1s,循環 5 次
count-down::after{
--t: 5;
counter-reset: time var(--t);
content: counter(time);
animation: count 5s steps(5) forwards,
shark 1s 5;
}
效果如下
是不是稍微有些突兀?因爲數字的變化是突然的,需要將數字的變化隱藏到透明度爲 0 的時候,爲了達到這種效果,只需要將閃爍動畫延遲 0.5 秒即可
count-down::after{
--t: 5;
counter-reset: time var(--t);
content: counter(time);
animation: count 5s steps(5) forwards,
shark 1s .5s 5; /*延遲 0.5s*/
}
這樣就自然多了
不過還有優化的空間。比如現在數字動畫有些太連貫了,如果希望數字出現後稍微停留一小會,或者說希望出現的慢一點,消失的快一點,如何處理呢?其實這比想象中的要容易許多,只需要改一下關鍵幀位置就行了,如下
@keyframes shark {
0%{
opacity: 1;
transform: scale(1);
}
20%{
opacity: 0;
transform: scale(0.4);
}
}
同時,延遲的時間也需要改成 0.8 秒,效果如下
這樣就實現了文章開頭所示效果
下面重點來了~ 完整代碼如下
@property --t {
syntax: '<integer>';
inherits: false;
initial-value: 0;
}
@counter-style stop {
system: cyclic;
symbols: "Go~";
range: infinite 0;
}
html,body{
margin: 0;
height: 100%;
display: grid;
place-content: center;
}
count-down{
display: flex;
align-items: center;
justify-content: center;
font-family: Consolas, Monaco, monospace;
font-size: 120px;
}
count-down::after{
--t: 5;
--dur: 1;
counter-reset: time var(--t);
content: counter(time, stop);
animation: count calc( var(--t) * var(--dur) * 1s ) steps(var(--t)) forwards,
shark calc(var(--dur) * 1s) calc(var(--dur) * .8s) calc(var(--t));
}
@keyframes count {
to {
--t: 0;
}
}
@keyframes shark {
0%{
opacity: 1;
transform: scale(1);
}
20%{
opacity: 0;
transform: scale(0.4);
}
}
你也可以訪問在線例子:CSS count-down(codepen.io)[5] 或者 CSS count-down(juejin.cn)[6]
另外,demo 中還有個小彩蛋,點擊可以重新運行動畫,實現方式如下
count-down:active::after{
animation: none;
}
四、其他動畫效果
除了縮放效果,還可以有一些位移的動畫,比如這樣的
@keyframes shark {
0%{
opacity: 1;
transform: translateY(0);
}
20%{
opacity: 0;
transform: translateY(100px);
}
}
效果如下
是不是有點奇怪?動畫不夠連貫,一會向下一會向上,有沒有辦法消失和出現都是從上到下的呢?當然也是可以的,實現如下
@keyframes shark {
0%{
opacity: 1;
transform: translateY(0);
}
20%{
opacity: 0;
transform: translateY(100px);
}
21%{
opacity: 0;
transform: translateY(-100px);
}
}
這裏多加了一個非常 “鄰近” 的關鍵幀,表示在透明狀態下,“迅速”改變位移,這樣在數字出現時的動畫就感覺是從上到下的,整體更爲流暢,效果如下
還可以調整一下前面的縮放效果,讓出來的時候更大,效果也更爲震撼
@keyframes shark {
0%{
opacity: 1;
transform: scale(1);
}
20%{
opacity: 0;
transform: scale(.4);
}
21%{
opacity: 0;
transform: scale(5);
}
}
效果如下
當然還有其他效果,比如旋轉,斜切等,這就需要發揮你的想象了~
五、總結和說明
以上就是本文的全部內容了,一個簡單的小動畫,你學會了嗎?下面總結一下實現要點:
-
複雜動畫可以分解成多個簡單的動畫
-
數字的變化可以通過多個標籤,改變位移實現
-
CSS 計數器可以將數字變量渲染到頁面
-
CSS @property 可以將 CSS 變量設置動畫,就像顏色變化一樣
-
CSS 計數器的好處是可以隨意更改類型,比如中文計數
-
倒計時的終點默認是數字 0 ,可以通過另一個動畫重置最後一幀
-
可以通過自定義 CSS 計數器,讓某個計數符號渲染成指定字符
-
縮放和透明的變化是同時進行的,可以放在一個動畫裏
-
數字的變化需要注意安排在透明度爲 0 的時候,不然數字變化很突兀
-
數字的出現和消失動畫可以添加一個鄰近的關鍵幀來快速歸位
另外,文中用了一些比較新的屬性,比如 @property,還有自定義計數器,不過沒關係,文中也都提到了其他解決方案,動畫的整體思路是不變的,如何觀察和分解動畫,這個纔是最重要的。最後,如果覺得還不錯,對你有幫助的話,歡迎點贊、收藏、轉發❤❤❤
前端偵探 致力於有趣的前端探索~ 公衆號
參考資料
[1] CSS @property: https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property
[2] 小 tips: 如何藉助 content 屬性顯示 CSS var 變量值: https://www.zhangxinxu.com/wordpress/2019/05/content-css-var/
[3] list-style-type: https://developer.mozilla.org/zh-CN/docs/Web/CSS/list-style-type
[4] CSS @counter-style 規則詳細介紹: https://www.zhangxinxu.com/wordpress/2021/10/css-counter-style/
[5] CSS count-down(codepen.io): https://codepen.io/xboxyan/pen/GRxKqPm
[6] CSS count-down(juejin.cn): https://code.juejin.cn/pen/7113470934589112327
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/MkdSVj_6j_oZfzBW_1JBxQ