Skip to main content

[Day 25] Animated Typography: 偷走你3秒的動態字卡

比起一般的標題,有時候加上些動畫的標題更為吸引人,特別是今天的動態字卡,絕對會吸住你的眼睛!? 今天我們來實作Day #23

CodePen: https://codepen.io/stevetanus/pen/XWqEeJq


1. HTML

<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>

circleline為一開始的動畫元素,後面會消失。 .hide是上下的檔板,擋住文字和引號,有揭開的動畫。 .bracket為兩邊的引號,.small.big為小文字和大文字。


2. SCSS(CSS)

.circle(動畫1秒)

.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.left, .line.right(延遲0.8秒,動畫1秒)

.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%的動畫效果。

我們再來看線段的動畫:

// 
@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(延遲1.7秒,動畫0.4秒)

.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(延遲2.1秒,動畫0.2秒)

&.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(延遲2.1秒,動畫0.2秒)

 &.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.top, .hide.bottom(延遲1.7秒,動畫0.4秒)

.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
}
}

.small(延遲2.2秒,動畫.5s)

小文字的動畫排在最後,透過translate來達到移動的效果。

@keyframes small-top {
0% {
translate: -20px; // small-bottom 則為20px
opacity: 0;
}
100% {
translate: 0px;
opacity: 1;
}
}

打包帶走(take away)

CSS

目標屬性
逐格動畫animation-timing-function: steps(n, <jumpterm>), step-start, step-end
引號.bracket加上偽元素:before:after,透過絕對位置調整
改變動畫位置,達到伸縮線跟檔板的應用transform-origin的變化

後記

動態字卡的動畫效果十分滑順,一個接著一個,有著好的延遲與動畫時間搭配,而在學習到step逐格動畫之後,也會使得動畫變得更加多元,感謝您的收看~快去把握剩下的周末時光吧!