最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Javascript typing effect - Stack Overflow

programmeradmin5浏览0评论

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.

It functions as a typing text effect, I want to be able to define the text it prints out from the webpage itself and not the script.

Javascript

var index = 0;
var text = 'Text';

function type()
{
    document.getElementById('screen').innerHTML += text.charAt(index);
    index += 1;
    var t = setTimeout('type()',100);
}

I've tried fiddling with the code and using them same method as my previous post, but I can't seem to get it to work.

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.

It functions as a typing text effect, I want to be able to define the text it prints out from the webpage itself and not the script.

Javascript

var index = 0;
var text = 'Text';

function type()
{
    document.getElementById('screen').innerHTML += text.charAt(index);
    index += 1;
    var t = setTimeout('type()',100);
}

I've tried fiddling with the code and using them same method as my previous post, but I can't seem to get it to work.

Share Improve this question edited May 23, 2017 at 11:53 CommunityBot 11 silver badge asked Nov 11, 2013 at 17:32 JakeGriffinJakeGriffin 2231 gold badge6 silver badges17 bronze badges 5
  • 7 Not a solution, but... don't pass strings to setTimeout. That uses eval, which is bad. You should be passing functions: var t = setTimeout(type, 100); – gen_Eric Commented Nov 11, 2013 at 17:34
  • 1 @JarrodRoberson This is not a duplicate of my previous post. It revolves around the same issue and the answer posted on the other post does not resolve this one. – JakeGriffin Commented Nov 11, 2013 at 17:37
  • 1 Check this one. – The Alpha Commented Nov 11, 2013 at 17:39
  • Agreed with you @JakeGriffin i did a positive vote on your question because it was -1 negatived by the guy that you are mentioning(JarrodRoberson). – Paulo Roberto Rosa Commented Nov 11, 2013 at 17:39
  • Thank you @PauloRoberto, I was wondering why it was downvoted. Also RCV, I'm checking that out now! It actually looks better that mine! – JakeGriffin Commented Nov 11, 2013 at 17:41
Add a comment  | 

7 Answers 7

Reset to default 7

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>

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>

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.

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>

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>

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);
    }
}

 let typeSpeed = 300;
    let deleteSpeed = 200;
    let wordDelay = 1000;

    // utility function that returns a promise that resolves after t milliseconds
    const delay = (t) => {
        return new Promise(resolve => {
            setTimeout(resolve, t);
        });
    }

    //Change Current Job
    const changeCurrentJob = async (wordsJson) => {
        //Get Current Job
        let currentJob = document.getElementById('wrap');
        for (let wordFromJson of wordsJson) {
            //Deleting
            //Previous word letters count
            let prevLetters = currentJob.innerHTML.split('');
            //Loop letters with for of to remove them
            for(let letterFromWordPrev of currentJob.innerHTML){
                //Remove Last letter
                prevLetters.pop();
                //Join Letters Array
                currentJob.innerHTML = prevLetters.join('');
                await delay(deleteSpeed);
            }

            //Typing
            for(let letterFromWord of wordFromJson){
                currentJob.innerHTML = currentJob.innerHTML+letterFromWord;
                //Type Speed
                await delay(typeSpeed);
            }
            //After finishing word Wait
            await delay(wordDelay);
            
        }
        //ReDO Typing - Declare Variables then Redo -
        let words = document.getElementsByClassName('typewrite');
        let wordsData = words[0];
        let wordsJson2 = JSON.parse(wordsData.getAttribute('data-type'));
        changeCurrentJob(wordsJson2);
    }
    
    // On window load Loop data-type And convert from json to txt and type
    window.onload = function() {
        let words = document.getElementsByClassName('typewrite');
        let wordsData = words[0];
        let wordsJson = JSON.parse(wordsData.getAttribute('data-type'));
        setTimeout(changeCurrentJob,wordDelay,wordsJson);
    };
<div class="typewrite" data-type='[ "Full Stack", "PHP", "JS" ]'>
  <div class="styledWarp" id="wrap"></div>
</div>

发布评论

评论列表(0)

  1. 暂无评论