18

次のコードを使用して、文字列を文字ごとに表示する必要があります。

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;

それは機能していません..何が間違っていますか?

4

9 に答える 9

36

次のようなことを試してください:

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必要なときに停止するように追加したことに注意してください。

于 2009-11-21T20:45:35.047 に答える
4

現在、18 のタイムアウトを定義しており、すべてが一度に ~ 実行されます。2 番目の問題は、実行する命令を文字列として渡すことです。その場合、評価されたコードはグローバル スコープで実行されるため、コードは 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);
        }
    })();
}
于 2009-11-21T20:46:37.697 に答える
3

@ yauhen-yakimovichによる回答よりもさらに一般的です:

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

コメントに示されている 2 つの間のわずかな違い --repeatメソッドはコールバックが実行された後にのみ繰り返されるため、「遅い」コールバックがある場合は、delayミリ秒ごとに実行されるのではなく、実行のたびに繰り返されますdelayが、loopメソッドはコールバックを起動します。毎delayミリ秒。途中で停止するにrepeatは、返される識別子としてオブジェクトを使用するため、clearTimeout(timer.t)代わりに使用します。

使用法:

@soufiane-hassou の回答と同じように:

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);
于 2013-03-18T19:16:58.413 に答える
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;
于 2009-11-21T20:39:04.967 に答える
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 が定義されていない (関数内で定義されている) ことです。

于 2009-11-21T20:46:27.870 に答える
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 でテスト済み。それが誰かを助けることを願っています。

編集>

次の更新により、重い「プロトタイピング」(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);
}
于 2012-11-12T14:14:02.740 に答える
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);
}
于 2014-03-10T13:21:48.800 に答える
0

あなたの for ループは一度にすべての文字のタイムアウトを設定しているため、それらは順番に表示されるのではなく、一度に表示されます。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);
    }
}
于 2009-11-21T20:44:18.950 に答える
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;

上記では、グローバル配列は 1 つしかありませんglo。ループでは、新しい配列メンバーを作成しgloappend()関数では、パラメーターとして渡されるインデックスを使用してこれらのメンバーを参照します。

注意: 2 番目のコード サンプルは、OP:s 問題に対する最適または最適な解決策を意図したものではありませんが、他の setTimeOut 関連の問題で役立つ可能性があります。誰かがプレゼンテーションやパフォーマンス テストを行いたい場合に、一部の機能を呼び出す必要がある場合に、少し遅れて呼び出します。このコードの利点は、for ループ (多くのコーダーは for ループを使用したい) を利用できることと、内部ループも使用できることと、ループ時間状態のローカル変数を timeOut 関数に "送信" できることです。

于 2012-12-18T11:33:44.227 に答える