Javascript typing effect

前端 未结 6 1303
刺人心
刺人心 2020-12-31 23:28

The issue arises from the same issue as last time. My websites run off a static domain, so I want to be able to use this script on each site without making duplicate copies.

相关标签:
6条回答
  • 2020-12-31 23:43

    Here is an approach using promises for sleeping between key presses.

    Here is a link for the repo at Github, but the code is basically this:

    class Typer {
    
        constructor(typingSpeed, content, output) {
    
            this.typingSpeed = typingSpeed;
            // Parses a NodeList to a series of chained promises
            this.parseHtml(Array.from(content), output);
        };
    
        makePromise(node, output) {
    
            if (node.nodeType == 1) // element 
            {
                // When a new html tag is detected, append it to the document
                return new Promise((resolve) => {
                    var tag = $(node.outerHTML.replace(node.innerHTML, ""));
                    tag.appendTo(output);
                    resolve(tag);
                });
    
            } else if (node.nodeType == 3) // text
            {
                // When text is detected, create a promise that appends a character
                // and sleeps for a while before adding the next one, and so on...
                return this.type(node, output, 0);
            } else {
                console.warn("Unknown node type");
            }
        }
    
        parseHtml(nodes, output) {
            return nodes.reduce((previous, current) => previous
                .then(() => this.makePromise(current, output)
                    .then((output) => this.parseHtml(Array.from(current.childNodes), output))), Promise.resolve());
        }
    
        type(node, output, textPosition) {
            var textIncrement = textPosition + 1;
    
            var substring = node.data.substring(textPosition, textIncrement);
    
            if (substring !== "") {
                return new Promise(resolve => setTimeout(resolve, this.typingSpeed))
                    .then(() => output.append(substring))
                    .then(() => this.type(node, output, textIncrement));
            }
    
            return Promise.resolve(output);
        }
    }
    
    0 讨论(0)
  • 2020-12-31 23:54

    If you want to define what text it prints out, you should pass the text through an argument, if I understand your question correctly.

    Try and mess with this:

    var type = function( elem , text , index )
    {
        var index = index||0;
        elem.innerHTML += text.charAt(index);
        index++;
    
        var t = setTimeout(function(){
            type( elem , text , index );
        },100);
    }
    type( document.getElementById('screen') , 'How\'re You?' );
    <p id="screen">Hello, </p>

    0 讨论(0)
  • 2020-12-31 23:56

    2 Years Later:

    Check out this awesome Typing & erasing effect plus a blinking cursor - CodePen

    In a Nutshell:

    var index = 0;
    var text = "The Typing Effect - In a Nutshell";
    
    function type(){
      var screenEl = $('#screen');
      screenEl.html(text.substr(0, index++));
    
      if (index < text.length) {
        // Feel free to type
        setTimeout('type()', 50);
      } else {
        // Reset and restart.
        index = 0;
        text = '';
      }
    };
    
    type();
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <p id="screen"></p>

    0 讨论(0)
  • 2021-01-01 00:02

    Nice question, LMGTFY has often given me a giggle in the past. I think you may find the following to be pretty easy to throw around anywhere. It's just a few attributes added to your target container, along with a call to get the typewriter started.

    Here, I run 4 of them simultaneously just for kicks. It's probably worth junking forEachNode in this example, instead using the few commented lines. If the result of getElementsByClassName was a true array, you could just call the .forEach method that arrays have. Unfortunately, a nodeList is similar but not the same - hence the need for such a function. I used it before realizing it probably clearer to do without it. In any case, it's a function I've found handy many times. I'll leave that in there as a thanks for such a fun question to consider.

    function forEachNode(nodeList, func) {
      var i, n = nodeList.length;
      for (i = 0; i < n; i++) {
        func(nodeList[i], i, nodeList);
      }
    }
    
    window.addEventListener('load', mInit, false);
    
    function typeWriter(el) {
      var myDelay = el.getAttribute('keyDelay');
    
      if (el.getAttribute('curIndex') == undefined)
        el.setAttribute('curIndex', 0);
    
      var curIndex = el.getAttribute('curIndex');
      var curStr = el.getAttribute('typewriterdata');
      el.innerHTML += curStr.charAt(curIndex);
      curIndex++;
      el.setAttribute('curIndex', curIndex);
    
      if (curIndex < curStr.length)
        setTimeout(callback, myDelay);
      else {
        if (el.getAttribute('nextline') != undefined) {
          var nextTgt = el.getAttribute('nextline');
          typeWriter(document.getElementById(nextTgt));
        }
      }
    
      function callback() {
        typeWriter(el);
      }
    }
    
    function mInit() {
      typeWriter(document.getElementById('line1'));
    
      var i, n, elementList;
      elementList = document.getElementsByClassName('autoType');
      forEachNode(elementList, typeWriter);
      //	n = elementList.length;
      //	for (i=0; i<n; i++)
      //		typeWriter( elementList[i] );
    }
    .multi {
      border: solid 2px #333333;
      width: 400px;
    }
    <body>
      <div class='autoType' typewriterdata='Enter this string letter by letter' keydelay='300'></div>
      <div class='autoType' typewriterdata='Enter this string letter by letter' keydelay='200'></div>
      <div class='autoType' typewriterdata='This is short but slooooow' keydelay='1000'></div>
      <div class='autoType' typewriterdata='The rain falls mainly on the plain in Spain' keydelay='100'></div>
    
      <div class='multi'>
        <div id='line1' typewriterdata='This is line 1' keydelay='300' nextline='line2'></div>
        <div id='line2' typewriterdata='This is line 2' keydelay='300' nextline='line3'></div>
        <div id='line3' typewriterdata='This is line 3' keydelay='300' nextline='line4'></div>
        <div id='line4' typewriterdata='This is line 4' keydelay='300'></div>
      </div>
    </body>

    0 讨论(0)
  • 2021-01-01 00:06

    Okay, I don't like any of the above code. Your original code also doesn't stop running once it reaches the end of the input text, and I don't believe any of the other suggested solutions stop either.

    Here's a rewritten function in pure JS:

    function type(i, t, ie, oe) {
        input = document.getElementById(ie).innerHTML;
        document.getElementById(oe).innerHTML += input.charAt(i);
        setTimeout(function(){
            ((i < input.length - 1) ? type(i+1, t, ie, oe) : false);
        }, t);
    }
    

    Which you can call like so:

    type(0, 100, "text", "screen");
    

    The parameters are: beginning index, speed, input element, output element

    Your HTML will look something like this:

    <div id="screen"></div>
    <div id="text" style="display:none">Hello Bobby</div>
    

    You can rename the divs to whatever you like, as long as you update the parameters accordingly. I'm sure there's an easier way to write this as well, but I like this method the most.


    Demo

    function type(i, t, ie, oe) {
        input = document.getElementById(ie).innerHTML;
        document.getElementById(oe).innerHTML += input.charAt(i);
        setTimeout(function(){
            ((i < input.length - 1) ? type(i+1, t, ie, oe) : false);
        }, t);
    }
    
    type(0, 100, "text", "screen");
    <div id="screen"></div>
    <div id="text" style="display:none">Hello Bobby</div>

    0 讨论(0)
  • 2021-01-01 00:07

    You can embed the text in the webpage itself in a hidden element like this:

    HTML

    <span id="hiddenText" style="display: none">Text you want to type out.</span>
    

    and then you can get the text from the webpage itself like this:

    Javascript

    var text = document.getElementById('hiddenText').innerHTML;
    

    Here is the jsfiddle you can see: http://jsfiddle.net/FMq6d/ . This makes minimal changes to your code.

    0 讨论(0)
提交回复
热议问题