Afficher le texte lettre par lettre

Quelle est la façon la plus élégante de montrer un texte html lettre par lettre (comme les légendes de jeux vidéo) en utilisant CSS et JavaScript?

Bien que je sois sûr que son peut être résolu en utilisant une approche de force brute (disons, diviser les caractères et les imprimer un par un en utilisant jQuery.append()), j'espère qu'il y a quelques CSS3 (pseudo-éléments?) ou jQuery magic pour le faire plus élégamment.

Points supplémentaires si la solution considère le contenu HTML interne.

23
demandé sur Xufox 2011-09-01 04:27:34

13 réponses

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

Appelez avec:

$(function () {
  showText("#msg", "Hello, World!", 0, 500);   
});
46
répondu armen.shimoon 2018-07-12 18:31:16

Si une révélation lisse est raisonnable, je pense que cela devrait être assez simple. Non testé, mais c'est ainsi que j'imagine que cela fonctionnerait

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

Ok, je n'ai pas pu résister et j'ai fait un violon. Une petite erreur de code que j'ai corrigée. Semble bon pour moi si!

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

11
répondu mrtsherman 2011-09-01 14:44:31

, Vous devriez vraiment juste append, ou afficher/masquer.

Cependant, si pour une raison étrange vous ne voulez pas modifier votre texte, vous pouvez utiliser ce morceau de code trop compliqué pour aucune bonne raison:

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

Et enfin, voici le violon: http://jsfiddle.net/dDGVH/236/

Mais, sérieusement, ne l'utilisez pas...

3
répondu Joseph Silber 2014-06-10 00:56:32

100% vanille javascript, mode strict, HTML discret,

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);
3
répondu BEAGM 2014-11-21 17:37:22

Quand j'ai fait cela, j'ai rencontré le problème d'un mot sautant de la fin d'une ligne à la mendicité de l'autre comme les lettres semblaient contourner cela, j'avais l'habitude de passer côte à côte, l'un dont le texte était transparent, l'autre visible et simplement déplacé les lettres une par une de la portée invisible au visible. Voici un violon.

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)
2
répondu hobberwickey 2015-08-02 16:16:23

J'ai fait un petit plugin jquery pour cela. Vous devez d'abord vous assurer que le texte sera visible si javascript est désactivé, et sinon, réafficher le texte lettre par lettre.

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

L'utilisation sera aussi simple que celle-ci:

$('h1').retype();
2
répondu Hazem_M 2016-11-26 19:00:52

Ceci est basé sur 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); 
    } 
}

Message [index++] ne fonctionnait pas dans ma page Web jquery-j'ai dû le changer en substr. De plus, mon texte original utilise du HTML et le texte tapé utilise le formatage HTML (br, b, etc.). J'ai également la fonction s'arrêtant si la cible a été cachée.

1
répondu Luke Wenke 2012-06-17 08:56:55

Vous devez envelopper chaque lettre dans la balise span, car les éléments HTML anonymes ne peuvent pas être stylés. Puis révéler une portée à la fois. Cela évite certains problèmes innerText / innerHTML (pas de rediffusion DOM?), mais peut-être exagéré dans votre cas.

0
répondu Mikko Ohtamaa 2011-09-01 00:43:55

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

})();

Vous pouvez améliorer ce code en le changeant de sorte que vous n'obtenez l'el qu'une seule fois en raison du fait qu'il faut un peu de ressources pour modifier le DOM.

0
répondu JDoe 2014-10-14 15:26:30

Il y a une bonne réponse à comment le faire ici: c'est une façon que vous pouvez manipuler chaque lettre avec tout .animate () propriété Disponible, pas avec des hacks comme couvrir le texte avec s etc.

0
répondu David Genger 2017-05-23 12:03:02

J'ai essayé de résoudre le même problème et j'ai trouvé cette solution qui semble fonctionner.

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);
});
0
répondu athinats 2016-03-30 16:32:30

Rendez votre code plus élégant en préparant des promesses pour chaque itération, puis exécutez-les comme deuxième étape où vous pouvez injecter la logique 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>
0
répondu Abdennour TOUMI 2017-12-19 06:11:27

Il y a quelques bibliothèques pour cela. Il y a TypeItJs et TypedJS les deux permettent au html d'être dans la chose que vous tapez ainsi que de nombreuses autres méthodes qui aident à animer les effets de la machine à écrire.

0
répondu Ryan Schaefer 2018-03-05 14:07:16