使用CSS和JavaScript逐字显示html文本(如视频游戏字幕)的最优雅方式是什么?
虽然我确信他可以使用蛮力方法解决(比如,分割字符并使用jQuery.append()
逐个打印),我希望有一些CSS3(伪元素) ?)或JQuery魔术更优雅地做到这一点。
如果解决方案考虑内部HTML内容,则为额外点。
答案 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 );
好吧,我无法抗拒并成了小提琴。我修复了一个小代码错误。虽然看起来不错!
答案 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)
答案 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
);
答案 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>