比起一般的標題,有時候加上些動畫的標題更為吸引人,特別是今天的動態字卡,絕對會吸住你的眼睛!?
今天我們來實作Day #23
CodePen: https://codepen.io/stevetanus/pen/XWqEeJq
<div class="frame">
<div class="circle"></div>
<div class="line left"></div>
<div class="line right"></div>
<div class="bracket left"></div>
<div class="bracket right"></div>
<div class="small top">more</div>
<div class="big">practices</div>
<div class="small bottom">less excuses</div>
<div class="hide top"></div>
<div class="hide bottom"></div>
</div>
circle
、line
為一開始的動畫元素,後面會消失。.hide
是上下的檔板,擋住文字和引號,有揭開的動畫。.bracket
為兩邊的引號,.small
跟.big
為小文字和大文字。
.circle {
...
animation: circle 1s ease-in-out;
animation-fill-mode: forwards; // 維持動畫結束時的狀態
}
// 放大1.2倍快速縮小消失
@keyframes circle {
0% {
scale: 1;
}
50% {
scale: 1.2;
}
90%, 100% {
scale: 0;
}
}
.line {
position: absolute;
z-index: 10;
width: 150px;
height: 4px;
top: 198px;
background: #fff;
scale: 0 1;
&.left {
left: 50px; // 左推50px
transform-origin: 100% 50%;
animation: lines 1s ease-in-out .8s, line-left 1s steps(1) .8s;
}
right: 50px; // 右推50px
transform-origin: 0% 50%;
animation: lines 1s ease-in-out .8s, line-right 1s steps(1) .8s;
}
}
transform-origin
使得.left
從右側開始動畫,.right
從左側開始動畫。
在line-left
的動畫中,animation-timing-function
設定為step(逐格動畫),steps(1)
跟steps(1, end)
是相同的(第1個參數是動畫的間隔數,第2個參數預設end),表示動畫在開始到結束間有一格動畫,並停在結束動畫的前一格,在這邊的話,會有0%跟50%的動畫效果。
MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/animation-timing-function
CSS動畫好文: https://ithelp.ithome.com.tw/articles/10200709
我們再來看線段的動畫:
//
@keyframes lines {
0% {
scale: 0 1;
}
50% {
scale: 1 1;
}
100% {
scale: 0 1;
}
}
// 中心從右邊跳到左邊
@keyframes line-left {
0% {
transform-origin: 100% 50%;
}
50% {
transform-origin: 0% 50%;
}
}
// 中心從左邊跳到右邊
@keyframes line-right {
0% {
transform-origin: 0% 50%;
}
50%{
transform-origin: 100% 50%;
}
}
配合steps(1)
,在動畫50%時轉換中心改變達到漂亮的線段伸縮效果。
.bracket {
position: absolute;
z-index: 10;
height: 70px;
width: 4px;
top: 165px;
background: #fff;
animation: bracket .4s ease-out 1.7s;
animation-fill-mode: both;
&:before, &:after {
position: absolute;
display: block;
content: '';
width: 25px;
height: 4px;
background: #fff;
}
.bracket
為白色直長條,:before
和:after
為頂端的橫短條
&.left {
left: 50px;
&:before {
top: 0;
left: 0;
transform-origin: 0% 50%;
animation: bracket-line .2s ease-out 2.1s;
animation-fill-mode: both;
}
&:after {
bottom: 0;
left: 0;
transform-origin: 0% 50%;
animation: bracket-line .2s ease-out 2.1s;
animation-fill-mode: both;
}
}
&.right {
right: 50px;
&:before {
top: 0;
right: 0;
transform-origin: 100% 50%;
animation: bracket-line .2s ease-out 2.1s;
animation-fill-mode: both;
}
&:after {
right: 0;
bottom: 0;
transform-origin: 100% 50%;
animation: bracket-line .2s ease-out 2.1s;
animation-fill-mode: both;
}
}
可以看到.left
跟.right
透過絕對定位來形成兩邊的引號
// 從中心長出y的長度
@keyframes bracket {
0% {
scale: 1 0;
}
100% {
scale : 1 1;
}
}
// 從給定的中心長出x的長度
@keyframes bracket-line {
0% {
scale: 0 1;
}
100% {
scale: 1 1;
}
}
.hide {
position: absolute;
z-index: 7;
width: 400px;
height: 40px;
background: #E16D6c;
left: 0;
animation: reveal .4s ease-out 1.7s;
animation-fill-mode: both;
&.top {
bottom: 49%;
transform-origin: 50% 0%;
}
&.bottom {
top: 49%;
transform-origin: 50% 100%;
}
}
為擋住中間80px(400*2%)的檔板,transform-origin
分別為頂部與底部,再加上動畫reveal形成打開檔板的效果。
@keyframes reveal {
0% {
scale: 1 1
}
100% {
scale: 1 0
}
}
小文字的動畫排在最後,透過translate
來達到移動的效果。
@keyframes small-top {
0% {
translate: -20px; // small-bottom 則為20px
opacity: 0;
}
100% {
translate: 0px;
opacity: 1;
}
}
CSS
目標 | 屬性 |
---|---|
逐格動畫 | animation-timing-function: steps(n, <jumpterm>) , step-start , step-end |
引號 | .bracket 加上偽元素:before 和:after ,透過絕對位置調整 |
改變動畫位置,達到伸縮線跟檔板的應用 | transform-origin 的變化 |
動態字卡的動畫效果十分滑順,一個接著一個,有著好的延遲與動畫時間搭配,而在學習到step
逐格動畫之後,也會使得動畫變得更加多元,感謝您的收看~快去把握剩下的周末時光吧!