一个字母一个字母地展示课文

Show text letter by letter

本文关键字:一个      更新时间:2023-09-26

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

如果一个平滑的揭示是合理的,那么我认为这应该是相当直接的。未经测试,但这是我想象的工作方式

<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%纯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,或者show/hide。

但是,如果出于某些奇怪的原因,您不想更改文本,则可以使用这段过于复杂而没有理由的代码:

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/

但是,说真的,不要用这个…

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

这是使用钩子的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>
 );
};
export default App;

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

看看代码沙箱

当我这样做的时候,我遇到了一个单词从一行的末尾跳到下一行的问题,因为它的字母似乎绕过了这个我习惯并排的跨度,其中一个文本是透明的,另一个是可见的,只是把字母一个接一个地从不可见的跨度移动到可见的。给你一把小提琴

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)

我做了一个小的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();

@armen的香草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>

这是基于armenian .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++]在我的jquery网页中不起作用-我不得不将其更改为substr。此外,我的原始文本使用HTML和文本键入使用HTML格式(br, b等)。如果目标被隐藏,函数也会停止

您需要在span标签中包装每个字母,因为匿名html元素无法设置样式。然后每次显示一个跨度。这避免了一些innerText/innerHTML问题(没有DOM回流?),但在您的情况下可能会过度。

香草

(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需要一些资源。

这里有一个很好的答案:这是一种方法,您可以使用任何可用的。animate()属性来操作每个字母,而不是像用s覆盖文本等hack。

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

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

现在有几个库可以做到这一点。有TypeItJs和TypedJS它们都允许html出现在你正在输入的东西中以及许多其他方法来帮助动画打字机效果

我要输入的答案是按字母显示文本的答案,但我对它做了一些改变

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;
}
function textRoll(message, interval){
   setTimeout(() => {
         para.innerHTML += message.charAt(0);
         return textRoll(message.slice(1))
   }, interval)
}

尝试使用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>

在这里使用仅CSS的方法,我将其用于打字样式。

<div class="rtypewriter mt-1" >  Text Letter be Letter  </div>
.rtypewriter{
  overflow: hidden; 
  white-space: nowrap;
  margin: 0 auto;
  letter-spacing: .15em;
  animation: typing 8s steps(60, end)
}
@keyframes typing {
  from { width: 0 }
  to { width: 100% }
}

希望它能帮助别人