JS实现动态打字效果

自己想用JS来实现一个动态打字的效果,然后对网上的一些方法做了一个总结

只打印单纯的文字

只打印文字时,就是循环打印字符串,字符串长度依次递增

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="text">

</div>
</body>
<script>
  let divTyping = document.getElementById('text')
  let i = 0,
    timer = 0,
    str = '用JS实现动态打字效果'

  function typing () {
    if (i <= str.length) {
      divTyping.innerHTML = str.slice(0, i++) + '_'
      timer = setTimeout(typing, 200)
    }
    else {
      divTyping.innerHTML = str//结束打字,移除 _ 光标
      clearTimeout(timer)
    }
  }

  typing()
</script>
</html>

这里写图片描述
如果只需要打印文字,上面的函数就足够用了。缺陷就是只能打印文字。


### 打印带标签的段落
<div id="source">
	打印带有标签的段落
	<p>我是段落</p>
	<ul>
		<li>列表1</li>
		<li>列表2</li>
		<li>列表3</li>
	</ul>
</div>

这里写图片描述
上面的方法是我参考的最牛的打字效果JS插件 typing.js,我自己理解后用ES6语法重新写了一遍,毕竟ES6是主流,并且有相当好工具去编译ES6。

原理
  1. 获取要打印的内容
  2. 将内容转化为字符和对象组成的数组中(对象是用来保存dom节点的)
  3. 获取数组的第一个元素并在原数组中删除,然后判断:是字符则打印;是对象,则创建dom节点,并重复第一步
  4. 数组长度为空时,判断对象是否有parent属性,有则回到第一步,没有则打印完毕

结合上面的例子我再重复一遍流程:
1.获取要打印的内容(id为source的div中的内容)
这里写图片描述
这里既有文本节点有有dom节点,将文本节点转化为字符串数组,将dom节点保存为对象,最后合并为一个数组
这里写图片描述
然后依次打印数组中的字符,若遇见保存dom的对象,在先创建节点再打印节点内容(节点内容中可能还会有dom节点),就这样依次打印完毕了

因为是克隆的节点,所以节点的样式都会存在
这里写图片描述

源码
<!DOCTYPE html>
<html>
<head>
    <title></title>
    <meta charset="utf-8" />
</head>
<body>

<div id="source">
    打印带有标签的段落
    <p>我是段落</p>
    <ul>
        <li>列表1</li>
        <li>列表2</li>
        <li>列表3</li>
    </ul>
</div>
<div id="output">

</div>

<script type="text/javascript">
  class Typing {
    constructor(opts) {
      this.opts = opts || {};
      this.source = opts.source;
      this.output = opts.output;
      this.delay = opts.delay || 120;
      this.chain = {
        parent: null,
        dom: this.output,
        val: []
      };
      if (!(typeof this.opts.done === 'function')) this.opts.done = function () {
      };
    }

    init() {
      //初始化函数
      this.chain.val = this.convert(this.source, this.chain.val);
    }

    convert(dom, arr) {
      //将dom节点的子节点转换成数组,
      let children = Array.from(dom.childNodes)
      for (let i = 0; i < children.length; i++) {
        let node = children[i]
        if (node.nodeType === 3) {
          arr = arr.concat(node.nodeValue.split(''))   //将字符串转换成字符串数组,后面打印时才会一个一个的打印
        } else if (node.nodeType === 1) {
          let val = []
          val = this.convert(node, val)
          arr.push({
            'dom': node,
            'val': val
          })
        }
      }
      return arr
    }

    print(dom, val, callback) {
      setTimeout(function () {
        dom.appendChild(document.createTextNode(val));
        callback();
      }, this.delay);
    }

    play(ele) {
      //当打印最后一个字符时,动画完毕,执行done
      if (!ele.val.length) {
        if (ele.parent) this.play(ele.parent);
        else this.opts.done();
        return;
      }
      let current = ele.val.shift()  //获取第一个元素,同时删除数组中的第一个元素
      if (typeof current === 'string') {
        this.print(ele.dom, current, () => {
          this.play(ele); //继续打印下一个字符
        })
      } else {
        let dom = current.dom.cloneNode() //克隆节点,不克隆节点的子节点,所以不用加参数true
        ele.dom.appendChild(dom)
        this.play({
          parent: ele,
          dom,
          val: current.val
        })
      }
    }

    start() {
      this.init();
      this.play(this.chain);
    }
  }
</script>
<script type="text/javascript">
  let source = document.getElementById('source')
  let output = document.getElementById('output')
  let typing = new Typing({
    source,
    output
  })
  typing.start()
</script>
</body>
</html>
  • 32
    点赞
  • 123
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
你可以使用 jQuery 的 `setInterval` 方法来实现动态打字效果。具体实现步骤如下: 1. 在 HTML 中创建一个包含文本内容的元素,例如一个 `div` 元素。 2. 在 JavaScript 中使用 jQuery 选择该元素,并将要显示的文本内容保存到一个变量中。 3. 使用 jQuery 的 `text` 方法将该元素的文本内容清空。 4. 定义一个 `index` 变量,表示当前要显示的字符在文本内容中的位置,初始值为 0。 5. 使用 `setInterval` 方法循环执行一个函数,该函数每次将文本内容中的下一个字符添加到元素中,并将 `index` 变量加 1,直到显示完全部文本内容为止。 以下是示例代码: HTML: ```html <div id="text"></div> ``` JavaScript: ```javascript $(document).ready(function() { var text = "这是要显示的文本内容。"; var index = 0; var intervalId = setInterval(function() { if (index < text.length) { $('#text').text($('#text').text() + text[index]); index++; } else { clearInterval(intervalId); } }, 100); // 每隔 100 毫秒执行一次函数 }); ``` 在上面的示例代码中,`text` 变量保存要显示的文本内容,`index` 变量表示当前要显示的字符在文本内容中的位置,`intervalId` 变量保存 `setInterval` 方法返回的 ID,用于在显示完全部文本内容后停止循环执行函数。`setInterval` 方法每隔 100 毫秒执行一次函数,该函数每次将文本内容中的下一个字符添加到 `div` 元素中,并将 `index` 变量加 1,直到显示完全部文本内容为止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值