注册

?十分钟学会打字动画

前言



背景知识:基本的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代码,我们避免了手动计算字符数量和步进数量,取得两全其美的结果:不仅动画生动逼真,而且代码易于维护!



链接:https://juejin.cn/post/7016226271067635748

0 个评论

要回复文章请先登录注册