I have a <div>
with text.
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
I'd like the text in this <div>
to appear on page one character at a time:
L Lo Lor ... and so on, until the full text is visible
Acceptable alternative: do that one word at a time, to avoid problems with HTML entities and jumpy words due to soft hyphenation.
If user clicks on the <div>
, it should cancel the animation and display the full text instantly.
In short, I want to imitate an animation that is frequently seen in Japanese-style adventure games. (I think that this is sometimes called a typewriter or teletype effect.) Here is a good example:
http://www.youtube.com/watch?feature=player_detailpage&v=SasgN0lim7M#t=418
Obviously, I can script the animation using JavaScript — just set up a timer and append letters (or words) one-by-one.
But is it possible to do what I need with CSS in modern browsers? (Of course, I'd need to at least change element class in the onclick
with JS, but that's OK.)
Update: To clarify on characters vs. letters and problems with HTML entities:
My text is littered with the HTML:
Lo­rem <i>ip­sum</i>.
Naïve approach with appending text to the innerHTML
character-by-character wouldn't work:
L Lo Lo& ...Doh!
You can achieve this with a bit of jQuery.
Check out my fiddle: http://jsfiddle.net/kA8G8/7/
HTML
<p class="typewriter">Nullam id dolor id nibh ultricies vehicula ut id elit. Maecenas faucibus mollis interdum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Cras justo odio, dapibus ac facilisis in, egestas eget quam.</p>
JS
var text = $('.typewriter').text();
var length = text.length;
var timeOut;
var character = 0;
(function typeWriter() {
timeOut = setTimeout(function() {
character++;
var type = text.substring(0, character);
$('.typewriter').text(type);
typeWriter();
if (character == length) {
clearTimeout(timeOut);
}
}, 150);
}());
Unfortunately you cannot do this with CSS so you will have to revert to a pure JS approach.
As your comments have explained, you require your text to contain some HTML markup so I would suggest a word-by-word animation being the easiest way to handle that. Something like this:
var timer, fullText, currentOffset, onComplete, wordSet;
function Speak(person, text, callback) {
$("#name").html(person);
fullText = text;
wordSet = text.split(" ");
currentOffset = 0;
onComplete = callback;
timer = setInterval(onTick, 300);
}
function onTick() {
currentOffset++;
if (currentOffset == wordSet.length) {
complete();
return;
}
var text = "";
for(var i = 0; i < currentOffset; i++){
text += wordSet[i] + " ";
}
text.trim();
$("#message").html(text);
}
function complete() {
clearInterval(timer);
timer = null;
$("#message").html(fullText);
if (onComplete) onComplete();
}
$(".box").click(function () {
complete();
});
Speak("Simon",
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
function () {
setTimeout(function () {
Speak("Javascript", "Simon has finished speaking!");
}, 2000);
});
Here is a working example
NOTE: This code can likely be vastly re-factored to be more efficient and concise, but it should demonstrate the concept in full.
I also created a letter-by-letter example. Although it doesn't support you html markup needs, it does look nicer so perhaps you can adapt it to work for you.
There is a pure CSS trick to do this.
Use a mask element, even a pseudo element p:before
or p:after
with a higher z-index than your text element. Give it the same color as the text background and the height of a line. Place it with absolute position just above the text.
Then you just have to animate it to make it move to the right, unmasking letter by letter. It's just a workaround, because if you have a complex background under the text, like an image, then this trick is difficult to reproduce because you will have to map the background image on the masking element.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With