0

I'm trying to come up with something to simulate an old school modem connection. I.E. text that paints itself at variable speeds rather than rendering at once.

Here's something that I've come up with that works:

http://jsfiddle.net/vUPK2/

The problem I have is that I can't get it to go any faster. I've got my setInterval set to 1ms, which seems to be as fast as I can get.

Does anybody have any idea how to re-factor this to remove the speed cap I'm experiencing?

Jeff Mitchell
  • 1,459
  • 1
  • 17
  • 33

5 Answers5

3

This seems a little bit faster, at least in FireFox. Despite the complete rewrite, the only real difference is not using jQuery or the string length property inside the "loop". I also added the ability to do more than one character at a time. 5-10 character seems a good range.

function TextTyper(targetElement, charsAtATime, textToType) {
    var i,
        l = textToType.length,
        timeout,
        el = $(targetElement)[0],
        textNode = el.childNodes[0];
    if (!textNode) {
        textNode = document.createTextNode('');
        el.appendChild(textNode);
    }
    this.begin = function() {
        i = 0;
        if (timeout) { clearTimeout(timeout); }
        textNode.nodeValue = '';
        typeChar();
    };
    console.log(textNode);
    function typeChar() {
        if (i < l) {
            textNode.nodeValue += textToType.substr(i, charsAtATime);
            i += charsAtATime;
            timeout = setTimeout(typeChar, 1);
        } else {
            timeout = 0;
        }
    }
}

(new TextTyper('#test', 8, 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam rhoncus urna vitae mi aliquet suscipit. Nullam vulputate ultrices tortor vel luctus. Duis sodales lacinia consequat. Vestibulum vehicula, ligula sit amet tincidunt scelerisque, orci arcu malesuada odio, eu ornare ipsum risus at metus. Nullam porttitor condimentum nunc, nec euismod massa consectetur id. Mauris ut nisl nulla, et tristique sem. In non ante vel libero lacinia vehicula in quis urna. Suspendisse urna erat, ornare sit amet rhoncus eget, bibendum at ipsum.'))
   .begin();

I observed some best practices with closures and scope here. But you should get rid of your TextTyper objects on page unload, and should dispose of them properly without creating new ones in tight loops (or you can leak memory with the closure on targetElement).

See this in action at jsfiddle.

Note: I chose setTimeout instead of setInterval because I didn't want multiple invocations of the same script to step on each other. Given the speed the code runs, I doubt that it could, but it's good design practice. If this were an Ajax call, you wouldn't want to saturate the server with requests before the answer from the first request had come.

ErikE
  • 48,881
  • 23
  • 151
  • 196
  • Nice, but: Why do you call clearTimeout with a function (and why at all)? Also, it would be much nice if you'd append to a textnode instead of using innerHTML. – Bergi Jul 25 '12 at 20:03
  • @Bergi If you call `begin()` again when it is already typing, it should start over. Also, you're absolutely right about the `clearInterval`. I was thinking it was like event attachment that requires a handle to the function, but it takes an integer handle, doesn't it? I fixed it now. More critique welcome. – ErikE Jul 25 '12 at 20:34
1

You can try appending more than one character at a time. Try appending 2 or 3 characters, or more.

Animation speed is dependent on frame rate and amount of change between frames.

kevin628
  • 3,458
  • 3
  • 30
  • 44
1

Yes, just add two letters (or more) in the displayText function. Do this in a for-loop and you can have a easy to adjust variable for it.

11684
  • 7,356
  • 12
  • 48
  • 71
1

Don't use jQuery when it comes to milliseconds-speed, and at least cache the references. To make the animation faster than the minimum timeout, you can only append more than one character a time. Especially if you want a similiar speed cross devices, you should use a longer timeout because the minimum value can vary - a standard animation speed is 60 frames per second.

function displayText(id, text) {
    var node = document.createTextNode(""),
        i = 0,
        chars = 5;
    document.getElementById(id).appendChild(node);

    (function add(){
        node.data += text.substr(i, chars);
        i += chars;
        if (i < text.length)
            setTimeout(add, 1000/60);
    })();
}

Demo at jsfiddle.net

Community
  • 1
  • 1
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

Alternative way

var txt="Lorem ipsum dolor sit amet";
index=0;
function displayText(text) {
    $('#test').append(text[index]); index ++;
    $('#test').append(text[index]); index ++;
    if (index  < text.length) {
        setTimeout(function(){ displayText(txt) }, 1);
    }
}

displayText(txt);

DEMO.

Or using a closer

function txt_show(text)
{
    var index=0;
    var txt=text;
    displayText();
    function displayText() {
        $('#test').append(txt[index]); index ++;
        $('#test').append(txt[index]); index ++;
        if (index  < txt.length) setTimeout(displayText, 1);
    }
}
var txt="Lorem ipsum dolor sit amet";
txt_show(txt);

DEMO.

But in IE it'll be slower (Only tested in IE8, FF and Chrome).

The Alpha
  • 143,660
  • 29
  • 287
  • 307
  • You mean, in IE it won't even run. Since IE doesn't support `string[index]`. At least, not IE 7. – ErikE Jul 25 '12 at 19:52
  • In IE 7.0.5730.13CO, when I click Run on your jsfiddle, nothing happens. So *infinitely slower*, maybe. – ErikE Jul 25 '12 at 19:58