逐字显示文本

IT技术 javascript jquery html css
2021-03-08 15:27:11

使用 CSS 和 JavaScript 逐字显示 html 文本(如视频游戏字幕)的最优雅方式是什么?

虽然我确信可以使用蛮力方法解决他的问题(例如,拆分字符并使用 一个一个地打印它们jQuery.append()),但我希望有一些 CSS3(伪元素?)或 JQuery 魔法来做到这一点更优雅。

如果解决方案考虑内部 HTML 内容,则额外加分。

6个回答

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);   
});
我相信 setTimeout 中的匿名函数是不必要的,因为它只包含一个函数调用,这是 setTimeout 本身的目的。setTimeout 可以将参数传递给函数,当您在延迟后添加它们时。所以,这应该有效 - 并且有效,正如我测试的那样:setTimeout(showText, interval, target, message, index, interval);
2021-04-21 15:27:11
@Luke:添加小提琴真的很有帮助!
2021-04-23 15:27:11
一旦它开始运行,你将如何阻止它继续?例如,假设这是在单击期间调用的。在它运行时,用户再次单击以在第一次调用完成之前显示另一条消息。这会导致两个循环重叠。你如何阻止第一个循环继续?
2021-05-05 15:27:11

如果平滑显示是合理的,那么我认为这应该非常简单。未经测试,但这就是我想象的工作方式

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

好吧,我无法抗拒并做了一个小提琴。我修复了一个小代码错误。不过对我来说看起来不错!

http://jsfiddle.net/mrtsherman/6qQrN/1/

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/

但是,说真的,不要使用这个......

+1 有趣的想法。可惜它同时显示了所有的行。也许可以通过一些更改来使其工作。
2021-05-07 15:27:11
@hgpc:当然可以,但这会涉及 2 个.cover跨度。这变得越来越复杂。您确定不想简单地追加吗?
2021-05-10 15:27:11
我很可能会使用 append,但无论如何我觉得你的想法很有趣。此外,它还具有保留内部 html 内容的优点。
2021-05-10 15:27:11

通过为每次迭代准备 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>