逐字显示文字

时间:2011-09-01 00:27:34

标签: javascript jquery html css css3

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

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

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

18 个答案:

答案 0 :(得分:48)

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

答案 1 :(得分:12)

如果顺利透露是合理的,那么我认为这应该是非常简单的。未经测试,但这是我想象它会起作用

<强> 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/

答案 2 :(得分:3)

你真的应该只是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/

但是,严重的是,不要使用它......

答案 3 :(得分:3)

100%香草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);

答案 4 :(得分:2)

当我这样做的时候,我遇到了一个单词的问题,从一行的末尾跳到下一行的乞讨,因为它的字母似乎绕过这个我用来并排跨越,其中一个是文本是透明的,另一个是可见的,只是简单地将字母从无形跨度移动到可见区域。这是一个fiddle

HTML

<div class='wrapper'>
  <span class='visible'></span><span class='invisible'></span>
</div>

CSS

.visible {
  color: black;
} 

.invisible {
  color: transparent;
}

JS

var text = "Whatever you want your text to be here",
    soFar = "";

var visible = document.querySelector(".visible"),
    invisible = document.querySelector(".invisible");

invisible.innerHTML = text;
var t = setInterval(function(){
  soFar += text.substr(0, 1),
  text = text.substr(1);

  visible.innerHTML = soFar;
  invisible.innerHTML = text;

  if (text.length === 0) clearInterval(t);
}, 100)

答案 5 :(得分:2)

我为此制作了一个小的jquery插件。首先,如果禁用了javascript,您需要确保文本可见,如果没有,则需要重新显示文本。

$.fn.retype = function(delay) {
    var el = this,
        t = el.text(),
        c = t.split(''),
        l = c.length,
        i = 0;
    delay = delay || 100;
    el.empty();
    var interval = setInterval(function(){
        if(i < l) el.text(el.text() + c[i++]); 
        else clearInterval(interval);
    }, delay);
};

用法就像这样简单:

$('h1').retype();

答案 6 :(得分:1)

这是基于armen.shimoon的:

var showText = function (target, message, index, interval) {    
    if (index <= message.length && $(target).is(':visible')) { 
        $(target).html(message.substr(0, index++)); 
        setTimeout(function () { showText(target, message, index, interval); }, interval); 
    } 
}

消息[index ++]在我的jquery网页中无效 - 我不得不将其更改为substr。我的原始文本也使用HTML,键入的文本使用HTML格式(br,b等)。如果目标已被隐藏,我也会停止功能。

答案 7 :(得分:1)

通过为每次迭代准备promises,使代码更加优雅,然后将其作为第二步执行,您可以在其中注入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>

答案 8 :(得分:0)

Vanillla

(function () {

var showText = function(target, msg, index, interval){

  var el = document.getElementById(target);

  if(index < msg.length){
    el.innerHTML = el.innerHTML + msg.charAt(index);
    index = index + 1;
    setTimeout(function(){
      showText(target,msg,index,interval);
    },interval);
  }

};


showText("id", "Hello, World!", 0, 50);   

})();

您可以通过更改它来改进此代码,因此您只需要获得el一次,因为它需要一些资源来修改DOM。

答案 9 :(得分:0)

如何做到这一点有一个很好的答案here: 这是一种可以使用任何.animate()属性操作每个字母的方法,而不是像使用s等覆盖文本的黑客一样。

答案 10 :(得分:0)

您需要在span标记中包装每个字母,因为无法对匿名html元素进行样式设置。然后一次显示一个跨度。这可以避免一些innerText / innerHTML问题(没有DOM重排?)但在你的情况下可能有点过分。

答案 11 :(得分:0)

我试图解决同样的问题,我想出了这个似乎有效的解决方案。

HTML

<div id='target'></div>

的jQuery

$(function() {
  var message = 'Hello world';
  var index = 0;

  function displayLetter() {
    if (index < message.length) {
      $('#target').append(message[index++]);
    }
    else{
      clearInterval(repeat);
    }
  }
  var repeat = setInterval(displayLetter, 100);
});

答案 12 :(得分:0)

现在有几个库。有TypeItJsTypedJS两者都允许html出现在您正在输入的内容中,以及许多其他有助于设置Typewriter效果动画的方法。

答案 13 :(得分:0)

我要输入的答案是答案Show text letter by letter,但是我对此做了一些更改

HTML

<h1>
    <span id="msg"></span>
</h1>

Javacript

var showText = function (target, message, index, interval) {    
  if (index < message.length) { 
    //$(target).append(message[index++]);
    $(target).text($(target).text() + message[index++]);
    setTimeout(function () { showText(target, message, index, interval); }, interval); 
  } 
}

$(function () { 
  showText("#msg", "Hello, World!", 0, 80);    
  //showText("#msg", "Hello, World!", 0, 500);
}); 

CSS

#msg {
    color: #6d67c6;
    font-family: sans-serif;
    font-size: 30px;
    font-weight: bold;
}

答案 14 :(得分:0)

@ armen.shimoon答案的香草JavaScript版本:

document.addEventListener('DOMContentLoaded', function() {

    showText("#msg", "Hello, World!", 0, 100);

});

let showText = function (target, message, index, interval) {
    if (index < message.length) {
        document.querySelector(target).innerHTML =
            document.querySelector(target).innerHTML + message[index++];
        setTimeout(function () { showText(target, message, index, interval); }, interval);
    }
}
<div id="msg"></div> 
<span id="text_target"></span>

答案 15 :(得分:0)

function textRoll(message, interval){
   setTimeout(() => {
         para.innerHTML += message.charAt(0);
         return textRoll(message.slice(1))
   }, interval)
}

答案 16 :(得分:0)

这是使用钩子的 React 版本。

import React, { useState, useEffect } from "react";
import "./styles.css";

const App = ({ speed, msg }) => {
  const Typer = ({ speed = 250, children = " Introduce your text" }) => 
{
  const [idx, setidx] = useState(0);
  useEffect(() => {
    const timer = window.setInterval(() => setidx((v) => v + 1), speed);
    return () => window.clearInterval(timer);
  });

  return <div>{children.substr(0, idx)}</div>;
};
return (
  <div>
    <Typer speed={speed} children={msg}></Typer>
  </div>
);

};

导出默认应用;

和主要的 index.js

import { StrictMode } from "react";
import ReactDOM from "react-dom";

import App from "./App";

const message2 = "This is some text to get typed on time";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <StrictMode>
    <App speed={100} msg={message2} />
  </StrictMode>,
  rootElement
);

看看code sandbox

答案 17 :(得分:0)

用 jquery 试试这个

var spanWidth = $('#text span').width();
$('#text').animate( { width: spanWidth }, 3000 );
div#text { width: 0px; height: 2em; white-space: nowrap; overflow: hidden;  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="text"><span>Hello World !</span></div>