大家好,我是 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…