偶然间发现Bun官网的这个打字、删除的效果,发现这是一个实现简单但还算炫酷的效果,所以尝试实现了下,并记录过程。
简单分析一下整个动画过程大概可以分为这么几步:
- 逐字删除:
handleDel - 删除完成后切换到下一个词组:
handleNext - 逐字输入:
handleType - 输入完成后光标会闪烁几秒(观察控制台dom可以发现其实闪烁只会发生在这个阶段):
handleBlink - 闪烁完后又开始逐字删除,无限循环。。。
完整代码如下,js代码就几十行:
<section>
<h1>
Bun is a fast JavaScript
<br />
<span id="typer">all-in-one-toolkit</span><span id="blink">|</span>
</h1>
</section>
* {
margin: 0;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #111;
}
section {
display: inline-block;
text-align: center;
}
h1 {
color: #fff;
text-align: left;
}
.blink {
margin-left: -5px;
}
.hidden {
visibility: hidden;
}
const typer = document.querySelector('#typer')
const blink = document.querySelector('#blink')
// 字符串索引数组
const strs = ['all-in-one-toolkit', 'runtime', 'package manager', 'bundler']
// 当前展示的字符串索引
let curIndex = 0
// 字符间的输入间隔
const interval = 50
const blinkInterval = 500
let blinkTimer = null
function handleType() {
let s = strs[curIndex]
let char = ''
let i = 0
const render = () => {
if (i === s.length) {
handleBlink()
return
}
char += s.charAt(i)
typer.innerHTML = char
i++
setTimeout(render, interval)
}
render()
}
function handleDel() {
let s = strs[curIndex]
let char = s
let i = s.length - 1
const render = () => {
if (i === -1) {
handleNext()
return
}
char = char.substring(0, i)
typer.innerHTML = char
i--
setTimeout(render, interval)
}
render()
}
function handleNext() {
curIndex = curIndex === strs.length - 1 ? 0 : ++curIndex
handleType()
}
function handleBlink() {
let count = 0
blinkTimer = setInterval(() => {
blink.classList.toggle('hidden')
if (count === 4) {
clearBlink()
handleDel()
}
count++
}, blinkInterval)
}
function clearBlink() {
clearInterval(blinkTimer)
blink.classList.remove('hidden')
}
function init() {
curIndex = 0
typer.innerHTML = strs[curIndex]
handleBlink()
}
init()