zoukankan      html  css  js  c++  java
  • 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。

    原理
    获取要打印的内容
    将内容转化为字符和对象组成的数组中(对象是用来保存dom节点的)
    获取数组的第一个元素并在原数组中删除,然后判断:是字符则打印;是对象,则创建dom节点,并重复第一步
    数组长度为空时,判断对象是否有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>

  • 相关阅读:
    oracle sql日期比较
    rlwrap真是一个好东西
    Dataguard 归档丢失处理
    oracle latch工作原理
    Latch free等待事件
    Redhat Enterprise Linux 5 安装 Oracle 10g release 2
    oracle 日期问题
    Oracle自动存储管理 ASMLib的支持变化
    [官方文档] oracle官方文档总汇(9i,10g,11gR1, 11gR2)
    实时分布式搜索引擎比较(senseidb、Solr、elasticsearch)
  • 原文地址:https://www.cnblogs.com/isuansuan/p/12738333.html
Copyright © 2011-2022 走看看