使用 CSS 和 JavaScript 逐字显示 html 文本(如视频游戏字幕)的最优雅方式是什么?
虽然我确信可以使用蛮力方法解决他的问题(例如,拆分字符并使用 一个一个地打印它们jQuery.append()
),但我希望有一些 CSS3(伪元素?)或 JQuery 魔法来做到这一点更优雅。
如果解决方案考虑内部 HTML 内容,则额外加分。
使用 CSS 和 JavaScript 逐字显示 html 文本(如视频游戏字幕)的最优雅方式是什么?
虽然我确信可以使用蛮力方法解决他的问题(例如,拆分字符并使用 一个一个地打印它们jQuery.append()
),但我希望有一些 CSS3(伪元素?)或 JQuery 魔法来做到这一点更优雅。
如果解决方案考虑内部 HTML 内容,则额外加分。
HTML
<div id="msg"/>
Javascript
var showText = function (target, message, index, interval) {
if (index < message.length) {
$(target).append(message[index++]);
setTimeout(function () { showText(target, message, index, interval); }, interval);
}
}
致电:
$(function () {
showText("#msg", "Hello, World!", 0, 500);
});
如果平滑显示是合理的,那么我认为这应该非常简单。未经测试,但这就是我想象的工作方式
html
<div id="text"><span>The intergalactic space agency</span></div>
css
div#text { width: 0px; height: 2em; white-space: nowrap; overflow: hidden; }
jQuery
var spanWidth = $('#test span').width();
$('#text').animate( { width: spanWidth }, 1000 );
好吧,我无法抗拒并做了一个小提琴。我修复了一个小代码错误。不过对我来说看起来不错!
100% vanilla javascript,严格模式,不显眼的 html,
function printLetterByLetter(destination, message, speed){
var i = 0;
var interval = setInterval(function(){
document.getElementById(destination).innerHTML += message.charAt(i);
i++;
if (i > message.length){
clearInterval(interval);
}
}, speed);
}
printLetterByLetter("someElement", "Hello world, bonjour le monde.", 100);
你真的应该只是append
,或显示/隐藏。
但是,如果出于某种奇怪的原因您不想更改您的文本,您可以使用这段过于复杂的代码:
HTML:
<p>I'm moving slowly...<span class="cover"></span></p>
CSS:
p {
font-family: monospace;
float: left;
padding: 0;
position: relative;
}
.cover {
height: 100%;
width: 100%;
background: #fff;
position: absolute;
top: 0;
right: 0;
}
jQuery:
var $p = $('p'),
$cover = $('.cover'),
width = $p.width(),
decrement = width / $p.text().length;
function addChar()
{
$cover.css('width', '-=' + decrement);
if ( parseInt( $cover.css('width') ) < width )
{
setTimeout(addChar, 300);
}
}
addChar();
最后,这是小提琴:http : //jsfiddle.net/dDGVH/236/
但是,说真的,不要使用这个......
通过为每次迭代准备 Promise 使您的代码更加优雅,然后作为第二步执行它们,您可以在其中注入 DOM 逻辑。
const message = 'Solution using Promises';
const typingPromises = (message, timeout) =>
[...message].map(
(ch, i) =>
new Promise(resolve => {
setTimeout(() => {
resolve(message.substring(0, i + 1));
}, timeout * i);
})
);
typingPromises(message, 140).forEach(promise => {
promise.then(portion => {
document.querySelector('p').innerHTML = portion;
});
});
<div ><p></p></div>