大家好,我是 Steven。
这期会介绍如何制作打字这个特效,这个教学分为两个部份。
首先是用纯 CSS 制作的简单版打字效果:
以及一个进阶版,动画效果更加细致及流畅,这就会用上 JavaScript:
那我们就开始吧。
这个教程的视频版本在 www.bilibili.com/video/BV1NV… ,欢迎三连关注!
HTML 的部分
打开 CodePen 编辑器,在 HTML 的部份加入一个 <h1> 标签,内容文字是 CodingStartup。
CSS 的部分
去到 CSS 的部份,先设定基础的文字大小,加入 :root 选择器,将文字大小设定为 20px。然后加入 body 选择器,用 Flex 的方法将内容上下左右置中。
加入 h1 选择器,将文字大小设定为 6rem,margin 和 padding 设定为 0。
好了,我们要实现打字效果,即是文字会逐一显示出来,在纯 CSS 的情况下,首先要套用一套等宽的字体,即是每一个文字的宽度都是相同的,尤其我们写代码的,编辑器用的字体几乎都是等宽字体,这样在阅读代码时才会更有效率。
将 font-family 设定为 monospace,这款字体也挺常用来作为编辑器的字体的。
CSS 中的 ch 单位
好了,这里介绍一个 CSS 的单位 ch,ch 是 character 的意思,即是一个单字,1ch 的宽度等于数目字 0 的宽度。
而由于我们用上了等宽字体,所以 1ch 就等于任何英文字、数字、符号等的宽度。好了,试试设定宽度是 1ch,然后加入 overflow: hidden,现在只是看到 C 这个字元:
改为 6ch 的话,就可以看到 Coding 6 个字了:
CSS 动画
来到这里,就差一个动画的设定。加入 @keyframes typing,并设定 from 和 to 两个动画的区块,from 的区块内设定宽度是 1ch,而 CodingStartup 总共有 13 个英文字,所以 to 的区块内设定宽度是 13ch。
回到 h1 的设定里面,加入 animation: 2s typing forwards,现在可以看到文字出现的效果:
不过打字是逐个字显示的,所以加入加速度函数的设定 steps(13, jump-none),代表这个动画会分为 13 格去显示,现在可以看到基础版的打字效果就已经完成了:
好了,我觉得现在的效果过于生硬,想将它改得优美一点,每个字随着游标快速滑入。
进阶版
先将宽度、overflow 以及动画的设定移除,然后加入 position: relative,现在会在文字后面加上游标。
加入 h1::after 伪类选择器,content 设定为空白字串,这样它才会显示出来。然后 display 设定为 inline-block,positon 设定为 absolute,宽度设定为 20px,高度设定为 6rem。背景颜色设定为黑色,然后配合一下字体,加入很小的圆角设定,border-radius 设定为 2px。再将它稍为向右移一点,right 设定为 -30px。
游标是会闪烁的,所以加入动画的设定 @keyframes cursor,加入 from 和 to 的区块,from 的 opacity 设定为 0,而 to 的 opacity 设定为 1。
再套用动画,设定 animation 是 1.1s cursor steps(2, jump-none) infinite,即是用 1.1 秒的时间执行名为 cursor 的动画。然后同样地,我想动画只用 2 个影格去显示,不要渐入渐出的效果,所以设定为 steps(2),然后 infinite 代表无限重覆这个动画:
好了,接着处理打字效果的部份,由于我想一个一个字进入,但又想每个字母都与游标有一种滑入的效果,所以我们首先要将每个文字都套用一个标签。
去到 JavaScript 的部份,定义一个常量 h1,获取 h1 这个元素。然后 h1.innerHTML 等于 h1.textContent.replace,通过正则表达式为每个字母都套上一层 <span>,现在可以通过开发者工具,确认已经套上:
然后就是逐字进入的效果,加入 h1 span 选择器,设定 display 是 inline-block,然后运用与刚才相同的原理,overflow 设定为 hidden,宽度设定为 0ch。现在每一个文字,即是 span 标签的宽度都是 0,只要将它改为 1ch,就会显示出来。
加入 @keyframes text-in,同样加入 from 和 to 的区块,from 的宽度设定为 0ch,to 的宽度设定为 1ch。
试试套用动画的设定,animation 设定为 1s text-in ease-in-out forwards,现在可以看到所有文字在同一秒钟滑入:
所以需要为每个文字加入一个动画延时的设定,这里会用到 CSS 的变量。加入 animation-delay,设定为 var(--delay),而这个 --delay 的设定值会在 JavaScript 那边赋予。
回到 JavaScript 的部份,加入 document.querySelectorAll('span'),用 forEach 将所有 span 通过回圈获取出来,在回圈外定义一个变量 delay,回圈每执行一次 delay 变量会加 1,然后运用 span.style.setProperty(),将延迟的秒数设定到 --delay 这个 CSS 变量上。
现在可以看到文字是一个接着一个出现的了,不过动画的速度太慢,我们将 1 秒改为 0.1 秒,以及判断当 index 等于 6 的时候,即是去到 Startup 那个 S 的时候再延迟多一点点,这样就更像是真实的打字情形。
好了,打字的效果基本上都完成了,再来最后一些优化。我想在打字过程中,游标是不闪烁的,打完后才闪烁。将闪烁的动画设定分拆出来,加入 h1.ended::after 选择器,将设定移到这里。即是当 h1 有 ended 这个 class 时游标才会闪烁。
在 JavaScript 中监听一下动画完成的事件,加入 h1 的 animationend 事件监听器,判断当 e.target 等于最后一个 span 的时候,为 h1 加上 ended 这个 class。
还有就是大家会发现 CodingStartup 这个字会完整出现,然后才开始打字的效果,原因是 animation-delay 的设定值一开始时是空值,所以就在没有延迟的情况下执行了一次。只需要为 --delay 加入一个比较大的预设值,例如 10s 就可以了。
我们来看看这个案例的完成效果
简单版(纯 CSS):
进阶版(JavaScript):
以上,就是这期要介绍的全部内容。
这个案例的源代码在 codepen.io/stevenlei/p…
你的支持是我的动力,请关注 CodingStartup 起码课,我们一起加油!
- B站: space.bilibili.com/451368848
- YouTube: youtube.com/codingstart…
- 掘金: juejin.cn/user/249773…