阅读 1717

🍊十分钟学会打字动画

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
本文已参与「掘力星计划」,赢取创作大礼包,挑战创作激励金。

前言

背景知识:基本的CSS动画逐帧动画闪烁效果

有些时候,我们希望一段文本中的字符逐个显现,模拟出一种打字的效果。这个效果在技术类网站中尤为流行,用等宽字体可以营造出一种终端命令行的感觉。如果使用得当,它确实可以让整个网页的设计感提升一个档次。

这篇文章我们就用CSS来实现一下这个效果~✨

解决方案

核心思路就是让容器的宽度成为动画的主体:

把所有文本包裹在这个容器中,然后让它的宽度从0开始以步进动画的方式、一个字一个字地扩张到它应有的宽度。

你可能已经察觉到了,这个方法是有局限的:它并不适用于多行文本。

好的,我们开始写代码吧!假设我们需要把这个动画效果应用到h1标题上,并且已经它把设置为等宽字体了,结构代码如下所示

<h1>CSS is awesome!</h1>
复制代码

🧑1.0版本

我们很容易地给他加上动画,让他宽度从0变化完整的宽度

/*
*1.0版本
*/
@keyframes typing {
    0% { width: 0 }
}

h1 {
  background: lightgreen;
  font: bold 200% Consolas, Monaco, monospace;
  width: 8.25em;
  animation: typing 8s ;
}
复制代码

20211007_145558.gif 我们可以看到产生的效果简直就是车祸现场😱,跟我们想要的的打字效果没有一点关系。

👦1.1版本

宝儿你可能已经猜到问题出在哪儿了,我们忘了用white-space:nowrap;来阻止文本折行,因此文本的行数会随着宽度的扩张不断变化。其次,我们忘了加上overflow: hidden;,所以超出宽度的文本没有被裁切掉。我们完善一下代码

/*
*1.1版本
*/
@keyframes typing {
    0% { width: 0 }
}

h1 {
  background: lightgreen;
  font: bold 200% Consolas, Monaco, monospace;
  width: 8.25em;
  white-space: nowrap;
  overflow: hidden;
  animation: typing 8s steps(15);
}
复制代码

20211007_144918.gif

值得注意的是我们这里的逐帧动画是通过设置steps实现的,我们所需要的步进数量是由字符的数量来决定的,这显然是很难维护的,而且对于动态文字来说更是不可能维护的。不过,我们稍后将看到,可以用一小段JavaScript代码来把这件事情自动化。

🕵️‍♂️2.0版本

20211007_150221.gif

/*
*2.0版本
*/
@keyframes typing {
	0% { width: 0 }
}

@keyframes caret {
	50% { border-right-color: transparent; }
}

h1 {
  /*background: lightgreen;*/
  font: bold 200% Consolas, Monaco, monospace;
  /* width: 8.25em; */
  width: 15ch;
  white-space: nowrap;
  overflow: hidden;
  border-right: .05em solid;
  animation: typing 8s steps(15),
	     caret 1s steps(1) infinite;
}
复制代码

2.0版本我们我们使用了ch单位,这个ch单位是由CSS值与单位(第三版规范引入的一个新单位,表示“0”字形的宽度。它应该是最不为人知的一个新单位,因为在绝大多数场景下,我们并不关心0这个字符显示出来到底有多宽。但对等宽字体来说,这是个例外。在等宽字体中,“0”字形的宽度和其他所有字形的宽度是一样的。因此,如果我们用ch单位来表达这个标题的宽度,那取值实际上就是字符的数量,在本例子中,也就是15。

同时我们添加了闪烁光标,我们用右边框来模拟光标效果,同时给光标设置闪烁的动画,将光标设置为透明即可,要注意的,光标的动画是无限循环的!

这个动画现在的表现相当完美了,不过还不是很易于维护:需要根据每个标题的字数来给它们分别指定不同的宽度样式,而且还需要在每次改变标题内容时同步更新这些宽度样式。显然,这种场景正是JavaScript的用武之地:

🕵️‍♀️2.1终极版本

20211007_150221.gif

/*
*2.1终极版本
*/
@keyframes typing {
	0% { width: 0 }
}

@keyframes caret {
	50% { border-right-color: transparent; }
}

h1 {
  font: bold 200% Consolas, Monaco, monospace;
  white-space: nowrap;
  overflow: hidden;
  border-right: .05em solid;
  animation: typing 8s,
	     caret 1s steps(1) infinite;
}
复制代码
const doc = document.querySelector('h1')
let len = doc.textContent.length, s = doc.style
s.width = len + 'ch'
s.animationTimingFunction = 'steps('+len+')'
复制代码

只需短短几行JavaScript代码,我们避免了手动计算字符数量和步进数量,取得两全其美的结果:不仅动画生动逼真,而且代码易于维护!

试一试

try it !

参考资料:《CSS揭秘》

最后

⚽本文带领大家实现了打字的动画效果,相信阅读完你一定有了不小的收获~
⚾如果你对这篇文章感兴趣欢迎点赞关注+收藏,更多精彩知识正在等你!😘
🏀GitHub 博客地址: github.com/Awu1227
🏉笔者还有其他专栏,欢迎阅读~
🏐玩转CSS之美
🎱Vue从放弃到入门
🎳深入浅出JavaScript

文章分类
前端
文章标签