简单实现Bun官网的打字删除效果

374 阅读1分钟

偶然间发现Bun官网的这个打字、删除的效果,发现这是一个实现简单但还算炫酷的效果,所以尝试实现了下,并记录过程。

bun.gif

简单分析一下整个动画过程大概可以分为这么几步:

  • 逐字删除: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()