web-dev-qa-db-fra.com

Afficher le texte lettre par lettre

Quel est le moyen le plus élégant de montrer un texte HTML lettre par lettre (comme les légendes de jeux vidéo) à l'aide de CSS et de JavaScript?

Bien que je sois sûr que son problème puisse être résolu en utilisant une approche de force brute (disons, en scindant les caractères et en les imprimant un à un en utilisant jQuery.append()), j'espère qu'il y aura des CSS3 (pseudo-éléments?) Ou la magie JQuery à faire. cela plus élégamment.

Points supplémentaires si la solution prend en compte le contenu HTML interne.

24
hpique

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

Appeler avec:

$(function () {
  showText("#msg", "Hello, World!", 0, 500);   
});
47
armen.shimoon

Si une révélation en douceur est raisonnable, alors je pense que cela devrait être assez simple. Non testé, mais voici comment 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 );

D'accord, je n'ai pas pu résister et j'ai fait du violon. Une petite erreur de code que j'ai corrigée. Cela me semble bien!

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

12
mrtsherman

Vous devriez vraiment juste append, ou afficher/masquer.

Toutefois, si, pour une raison quelconque, vous ne souhaitez pas modifier votre texte, vous pouvez utiliser ce morceau de code excessivement compliqué:

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, n'utilisez pas ça ...

3
Joseph Silber

100% javascript vanille, 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
BEAGM

J'ai fait un petit plugin JQuery pour cela. Tout d’abord, vous devez vous assurer que le texte sera visible si javascript est désactivé, sinon, réaffichez 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 cela: 

$('h1').retype();
2
Hazem_M

Lorsque j’ai fait cela, j’ai rencontré le problème d’un mot sautant de la fin d’une ligne à la mendicité de la suivante. les autres lettres visibles et simplement déplacées une par une de la portée invisible à la 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
hobberwickey

Rendez votre code plus élégant en préparant des promesses pour chaque itération, puis exécutez-les dans un deuxième temps, où vous pourrez 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>

1
Abdennour TOUMI

Ceci est basé sur armen.shimoon's:

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 - je devais le changer en substr. De plus, mon texte d'origine utilise HTML et le texte saisi utilise le formatage HTML (br, b, etc.). J'ai aussi la fonction qui s'arrête si la cible a été cachée.

1
Luke Wenke

Vanille

(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 le el qu'une fois car il faut un peu de ressources pour modifier le DOM. 

0
JDoe

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

0
Mikko Ohtamaa

il y a une bonne réponse comment le faire ici : C'est une façon de manipuler chaque lettre avec n'importe quelle propriété .animate () disponible, pas avec des hacks comme si on couvrait le texte avec s etc.

0
David Genger

J'essayais de résoudre le même problème et j'ai proposé 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
athinats

Il y a quelques bibliothèques pour cela maintenant. 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 Typewriter.

0
Ryan Schaefer