這篇主要是說明如何運用幾個 CSS 和 JS 觀念來做出打字機的效果。
話不多說,先看 DEMO:
DEMO
主要觀念
- CSS
- keyframes
- animation 設定
- JS
- setInterval()
- contains()
- if, else
程式碼說明
HTML
先從 HTML 結構來說:
第一層 div 是為了設定鼠標的活動空間是和字體寬度相等,因此會設定為 display: inline-block
第二層 div (#typewrite-animated) 則是打字機動畫效果的設定層
再往內是打字機文字顯示的地方 (#typewrite-text)1
2
3
4
5<div class="d-inline-block">
<div id="typewrite-animated">
<span id="typewrite-text" class="d-inline-block"></span>
</div>
</div>
CSS
接著來看 CSS 樣式設定的部分
如同上面 HTML 區塊提到的,為了讓寬度適應內容,會設定 display: inline-block。因此第一個樣式就是:1
2
3.d-inline-block {
display: inline-block;
}
接著進入重點的鼠標以及打字機效果的說明。
我們把主要的動畫效果寫到 .typewriter span,而 typewriter 就是要加到 #typewrite-animated 並動態被切換的 class1
2
3
4
5
6
7
8
9.typewriter span {
font-size: 72px;
overflow: hidden;
border-right: .3rem solid $dark;
white-space: nowrap;
animation:
typing 0.6s steps(3, end),
blink-caret .5s step-end infinite;
}
font-size
: 設定字體大小overflow: hidden
: 隱藏文字顯示border-right
: 設定鼠標寬度white-space: nowrap
: 讓文字不換行animation
: 設定動畫
animation
這邊要特別說明動畫的部分,有加上兩個值。
第一個是 typing 0.6s steps(3, end)
typing 0.6s steps(3, end)
中的第一個參數 typing 是說明動畫名稱,會對應到 keyframe 的設定1
2
3
4@keyframes typing {
from { width: 0 }
to { width: 100% }
}
也就是外部的寬度由 0 到 100%,而 0.6s 則是指這個動畫過程的時間,第三個參數則是指 animation-timing-function。animation-timing-function 這個屬性是用來控制動畫播放的速度與加速度,常見的值有 linear、ease-in、ease-out 等等,而這邊使用的 steps 也是其中的值,這邊就來介紹一下 steps 吧!
steps()
steps 中可以帶兩個參數,第一個是數字,代表的是要將動畫切為幾格,第二個 position 是指動畫從斷點頭或是斷點尾開始。
從 W3C 的圖來看是這樣:
圖片來自 W3C
實際從範例可以更清楚地理解,請打開以下範例:
https://codepen.io/carlos411/pen/wRKRej
範例來自 Carlos-Studio 設計好網站
到這邊就可以了解 steps() 的使用,可以讓文字變成一個一個出現。而範例呈現的文字數有 3 個,所以 steps 設定是 3。以此類推,若有五個字就 steps 就設定為 5。
而第二個值 blink-caret .5s step-end infinite;
用法也如同上面提到的,blink-caret 是動畫名稱,對應的 keyframes 是設定鼠標的閃爍效果,由透明到黑色。1
2
3
4@keyframes blink-caret {
from, to { border-color: transparent }
50% { border-color: $dark }
}
同樣使用 step-end 讓鼠標有閃動的感覺,最後參數 infinite 讓動畫可以持續的重複播放
JS
最後說明一下 JS 的部分:
主要是透過 setInterval() 來做每一次的切換變化
1 | // 透過 arr 陣列儲存要變化的文字內容 |
JS 補給站:
animationend event
animationend 事件,就如同 click 事件一樣,可以透過 addEventListener 來對元素做監聽。animationend 是指在 CSS 動畫執行完後再執行後面函式設定的內容
contains()
contains 方法可以用在 DOMTokenList,而元素的 classList(ele.classList)回傳的正是一個 DOMTokenList 物件,所以這邊要確認是否有某個 class 就需要使用 contains。
有一個與 contains 很像的方法,也就是 Array 的 includes,要注意這邊若要使用 includes,要先將 DOMTokenList 轉為 Array。
例如:[...typewriteAni.classList].includes('typewriter')