如何在浏览器实现文字打字机输入效果

111次阅读
没有评论

共计 3243 个字符,预计需要花费 9 分钟才能阅读完成。


我们看到有些网站的文字会有类似于输入的效果,就好像 自动打字 一样,虽然这个效果用的地方可能不多,但如果用的好的话可能会有奇效,比如在博客、演讲展示等方面应用。那么,怎么实现呢?

使用 setTimeout 实现

第一种方法是使用 setTimeout 进行文字控制,每一个文字都是一个 span,利用 DOM 操作以一定的间隔将每个文字添加到文档中,同时设置opacity:1 使其显示出来。光标闪烁的效果则利用 border-left 进行 animation 动画展示。

HTML 结构

先看代码:

<div class="container">
  <article class="input-container">
      <!-- 这里是需要展示的原始文字,设为 display:none;-->
    <p class="originWords">Hello world!</p>
  </article>
  <article class="typewriter-container">
      <!-- 这里是最终有文字输入效果的文字 -->
    <p class="typewriter-output"></p>
  </article>
</div>

解释一下,我们首先把原始文字设为 display: none;,这样不会占用文档位置,然后我们给之后添加的文字span 块指定 class 为word

CSS 设置

先看代码:

.container {
  width: 100%;
  display: flex;
  justify-content: center;
}

.input-container {display: none;}
.typewriter-container {width: 50%;}
.word {
  opacity: 0;
  transition: opacity 2s step-start;
}
.typewriter-output:after {
  display: inline-block;
  content: '';
  vertical-align: -1px;
  height: 14px;
  width: 1px;
  border-left: 2px solid black;
  margin-left: 2px;
  animation: shine 1s infinite;
}
@keyframes shine {
  50% {border-left: 0;}
}

我们对 word 设置 transition: opacity 2s step-start;。这里之所以通过opacity 来进行 transition,是因为 transition 不支持 display,而opacity 只需要设置 01就可以使元素进行显示而不需要重排。

这里 transition-timing-function 使用 step-start,使其有跳跃的效果,step-start 相当于 steps(1, jump-start)steps(n, <jumpterm>) 代表 transition 会停顿 n 次,每一次的效果为 <jumpterm>jump-start 代表第一个跳跃发生在 transition 刚开始的时候,更多效果见 文档

为什么要使用 :after 呢?因为我是逐步向 typewriter-output 添加 span 块,所以一开始宽度是不确定的,而且光标高度也不好设置,所以我想了个笨方法,使用 after 伪元素生成一个光标,并用 animation 控制其 border-left 的显示。但这里有个 bug 就是文字显示的间隔不能超过 300ms,所以说这样处理还是有些问题,以后可能会有更好的方法。

JS 部分

其实就是利用 setTimout 设置时间间隔,通过 DOM 操作进行添加文字,先看代码:

var words = document.querySelector('.originWords').innerText;
var output = document.querySelector('.typewriter-output');
var word = null;
var lastWord = null;

for (var i = 0, l = words.length; i< l; i++) {setTimeout(writeWord(i), i * 200);    // 每隔 0.2s 输出一个文字
}
// 这里使用闭包保存 i
function writeWord(index) {return function () {word = document.createElement('span');
    word.classList.add('word');
    output.appendChild(word);
    if (!lastWord) {lastWord = word;}

    if (lastWord !== word) {lastWord.style.opacity = '1';}
    word.innerText = words[index];
    lastWord = word;
    if (index === words.length - 1) {lastWord.style.opacity = '1';}
  }
}

代码部分很简单,就是先获取需要展示的文字内容,然后每个字都通过 dom 操作塞进去,设置opacity:1,再进行一下边界判断,就实现了文字的展示。


纯 animation 实现

这次我们不用 setTimeout,所有展示的动画全部用animation 来实现。废话不多说,我们来看一下。

HTML 结构

<h1 id="typewriter">Hello, My friend.</h1>

这种方法的好处就是不用有一个隐藏的原始文字段落,直接显示想显示的内容。

CSS 设置

接下来我们设置 CSS:

body {
    background: black;
    color: #fff;
}

h1 {
    font: bold 100% monospace;
    border-right: 0.1em solid;
    margin: 2em 1em;
    white-space: nowrap;
    overflow: hidden;
}

@keyframes typing {
    from {width: 0;}
}

@keyframes cursor-blink {
    50% {border-color: transparent;}
}

看起来很简单对不对?挨?说好的动画呢?别急,我们通过 JS 来设置animation

JS 部分

先看代码:

var typewriter = document.getElementById('typewriter');
var words = typewriter.innerText.length;
if (words) {
    typewriter.style.width = words + 'ch';
    typewriter.style.animation = 'typing 3s steps(' + words + ', end), cursor-blink 0.5s step-end infinite alternate';
}

这里我们所做的事就是获取文字段落字符串的长度,然后设置其宽度和动画效果。非常简单!

那么,为什么这样做可以呢?别急,我们来分析分析。

首先,在获取了文字字符串长度后,我们设置段落的宽度为 width: Xch;,这里 X 代表字符串长度,ch 是长度单位,代表数字“0”的宽度,通常也就是一个字符的宽度。

然后,我们直接设置动画:
animation: typing 3s steps(X, end), cursor-blink 0.5s step-end infinite alternate;
一切就搞定了!为啥?通过 CSS 我们设置了 @keyframetyping,表示宽度从 0 开始,一直到设置的Xch,持续 3s,用steps 动画函数,分为 X 步,也就是有多少个字符,就停顿多少下,达到输入的效果。至于光标的效果,我们直接通过动画设定 50% 的时候 border-colortransparent,则每一秒闪烁一次,因为只有 border-right 设置了宽度,所以完美达到光标的效果。

总结

两种方法比较起来,第二种方法更加实用简便,推荐大家使用。这只是简单的 CSS3 animation 动画应用,今后还可以开动脑筋,实现更多炫酷有趣的效果。

正文完
 
西蒙
版权声明:本站原创文章,由 西蒙 2019-01-23发表,共计3243字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
验证码