我想要一个字符串,使用以下代码显示字符:
function initText()
{
var textScroller = document.getElementById('textScroller');
var text = 'Hello how are you?';
for(c = 0; c < text.length; c++)
{
setTimeout('textScroller.innerHTML += text[c]', 1000);
}
}
window.onload = initText;
它不起作用..我做错了什么?
答案 0 :(得分:35)
尝试这样的事情:
function initText()
{
var textScroller = document.getElementById('textScroller');
var text = 'Hello how are you?';
var c = 0;
var interval = setInterval(function() {
textScroller.innerHTML += text[c];
c++;
if(c >= text.length) clearInterval(interval);
}, 1000);
}
注意我添加了clearInterval
以在需要时停止它。
答案 1 :(得分:4)
目前,您正在定义18个超时,所有将立即执行。 第二个问题是,您将指令作为String传递。在这种情况下,代码将无法访问initText中定义的所有变量,因为已评估的代码将在全局范围内执行。
IMO,这应该做的工作
function initText(){
var textScroller = document.getElementById('textScroller');
var text = 'Hello how are you?';
var c = 0;
(function(){
textScroller.innerHTML += text.charAt(c++);
if(text.length > c){
setTimeout(arguments.callee, 1000);
}
})();
}
答案 2 :(得分:3)
@ yauhen-yakimovich比answer更通用:
Timeout
:var repeat = (function () {
return function repeat(cbWhileNotTrue, period) {
/// <summary>Continuously repeats callback after a period has passed, until the callback triggers a stop by returning true. Note each repetition only fires after the callback has completed. Identifier returned is an object, prematurely stop like `timer = repeat(...); clearTimeout(timer.t);`</summary>
var timer = {}, fn = function () {
if (true === cbWhileNotTrue()) {
return clearTimeout(timer.t); // no more repeat
}
timer.t = setTimeout(fn, period || 1000);
};
fn(); // engage
return timer; // and expose stopper object
};
})();
Interval
:var loop = (function () {
return function loop(cbWhileNotTrue, period) {
/// <summary>Continuously performs a callback once every period, until the callback triggers a stop by returning true. Note that regardless of how long the callback takes, it will be triggered once per period.</summary>
var timer = setInterval(function () {
if (true === cbWhileNotTrue()) clearInterval(timer);
}, period || 1000);
return timer; // expose stopper
};
})();
注释中指示的两者之间略有差异 - repeat
方法仅在回调执行后重复,因此如果您有“慢”回调,它将不会每delay
ms运行一次,但执行后每delay
次重复,而loop
方法将每隔delay
ms触发一次回调。要提前停止,repeat
会使用对象作为返回的标识符,因此请改用clearTimeout(timer.t)
。
就像@ soufiane-hassou的answer一样:
var textScroller = document.getElementById('textScroller');
var text = 'Hello how are you?';
var c = 0;
var interval = repeat/* or loop */(function() {
textScroller.innerHTML += text[c];
c++;
return (c >= text.length);
}, 1000);
如前所述,过早停车将是:
/* if repeat */ clearTimeout(interval.t);
/* if loop */ clearInterval(interval);
答案 3 :(得分:2)
试试这个:
function initText()
{
var textScroller = document.getElementById('textScroller');
var text = 'Hello how are you?';
for(c = 0; c < text.length; c++)
{
setTimeout("textScroller.innerHTML += '" + text[c] + "'", 1000 + c*200);
}
}
window.onload = initText;
答案 4 :(得分:1)
尝试使用闭包:
function init() {
var textScroller = document.getElementById('textScroller');
var text = 'Hello how are you?';
var c = 0;
function run() {
textScroller.innerHTML += text[c++];
if (c<text.length)
setTimeout(run, 1000);
}
setTimeout(run, 1000);
}
init()
您的代码中的问题是您放入字符串的代码将在全局上下文中运行,其中未定义textScroller(它在您的函数中定义)。
答案 5 :(得分:1)
我想分享一个片段(根据Soufiane Hassou的回答)。它延伸到这样一种情况,即你在一个固定的时间间隔内替换一个for循环体来迭代某个数组。基本相同的同步循环,但“睡眠”暂停(因为javascript不是同步编程语言)。
function loop(arr, take, period) {
period = period || 1000;
var i = 0;
var interval = setInterval(function() {
take(i, arr[i]);
if (++i >= arr.length) { clearInterval(interval);}
}, period);
}
用法示例:
loop([1, 2, 3, 4], function(index, elem){
console.log('arr[' + index + ']: ' + elem);
});
在Node JS中测试过。希望有所帮助。
<强>编辑&gt; 强>
以下更新使代码可以与libs一起使用繁重的“原型设计”(如jQuery或原型):
function loop(arr, take, period) {
period = period || 1000;
var scope = {
i: 0,
arr: arr,
take: take,
};
var iterate = (function iterate() {
if (this.i >= this.arr.length) { clearInterval(this.interval); return}
take(this.i, this.arr[this.i++]);
}).bind(scope);
scope.interval = setInterval(iterate, period);
}
答案 6 :(得分:0)
你的for循环正在为每个字符设置一次超时,因此它们不会按顺序出现,而是一次性出现。你的setTimeout应该包含另一个setTimeout的代码,该setTimeout将包含要显示的下一个字符。
这样的事情(没有测试过这个)
function initText()
{
var textScroller = document.getElementById('textScroller');
var text = 'Hello how are you?';
setTimeout('nextChar(text)', 1000);
}
function nextChar(text){
if(text.length > 0){
textScroller.innerHTML += text[0];
setTimeout('nextChar(text.substring(1))', 1000);
}
}
答案 7 :(得分:0)
如果你想保留setTimeOut(而不是setInterval)并使用命名函数(而不是在setTimeOut调用中评估代码块),那么这可能会有所帮助:
var b = {
textScroller: document.getElementById('textScroller'),
text: "Hello how are you?"
};
function initText() {
for(c = 0; c < b.text.length; c++) {
setTimeout("append("+c+")", 1000 + c*200);
}
}
function append(c) {
b.textScroller.innerHTML += b.text[c];
}
window.onload = initText;
通过上述内容,您可以将参数传递给追加函数。
要传递几个参数,下一个代码可以解决问题:
var glo = [];
function initText()
{
var textScroller = document.getElementById('textScroller');
var text = "Hello how are you?";
var timeout_time;
for(c = 0; c < text.length; c++) {
glo[glo.length] = {text:text, c:c, textScroller:textScroller};
timeout_time = 1000 + c * 200;
setTimeout("append(" + (glo.length - 1) + ")", timeout_time);
}
}
function append(i)
{
var obj = glo[i];
obj.textScroller.innerHTML += obj.text[obj.c];
obj = null;
glo[i] = null;
}
window.onload = initText;
通过上述内容,您只有一个全局数组glo
。在循环中,您创建新的数组成员到glo
,在append()
函数中使用索引来引用这些成员,该索引作为参数传递。
注意:第二个代码示例并不是OP问题的最佳或最合适的解决方案,但可能会受益于其他setTimeOut相对问题,例如。当有人想要进行演示或性能测试时,需要在延迟后调用某些功能。这段代码的优点是可以使用for循环(许多编码器想要用于循环)以及使用内部循环的可能性以及将循环时间状态中的局部变量“发送”到timeOut函数的能力。
答案 8 :(得分:0)
可能更好地循环级联。例如,淡化div:
div=document.createElement('div');
div.style.opacity=1;
setTimeout(function(){fade(1);},3000);
function fade(op){
op-=.05;
if(op>0) setTimeout(function(){div.style.opacity=op;fade(op);},30);
else document.body.removeChild(div);
}