2016-08-01 1 views
0

jsで "console typing effect"を作成しようとしています。次の関数では要素のテキストを取ります。そのテキストをスライスして遅れてペーストします。forループ内でsetTimeoutが渡された関数を実行していません

クロムのコードをデバッグした後、私はjavascriptがsetTimeoutを実行していないことがわかります。ただ無視するだけです。

function type() { 
    var text = document.querySelector('.console-effect').textContent; 
    for (var i = 0; i <= text.length; i++) { 
     setTimeout(function() { 
      document.querySelector('.console-effect').textContent = text.substr(0, i) 
     }, 50); 
    } 
} 
type(); 
+1

あなたがsetTimeoutを "それだけ無視" とはどういう意味ですか?匿名関数が実行されているかどうかを確認するためにデバッグ 'console.log()'を入れましたか?とにかく、私はすぐにあなたが問題を起こしているのを見ることができます。ループの繰り返しごとに 'i'の値を「閉じる」必要があります。そうしないと、コードが期待どおりに実行されません。クロージャで 'setTimeout()'コールをラップしてみてください。 – jered

答えて

3

あなたsetTimeout sがすべて同時に実行しているを使用する必要があります。 50*iのような値を使用して、各タイムアウトを遅延させる必要があります。

この場合、iの値を保持するには、クロージャを使用する必要があります。それ以外の場合は、タイムアウトが終了するまでにループが終了し、すべての場合にはiが最終値になります。

var text = document.querySelector('.console-effect').textContent; 
 

 
for (var i = 0; i <= text.length; i++) { 
 
    (function(i) { 
 
    setTimeout(function() { 
 
     document.querySelector('.console-effect').textContent = text.substr(0, i); 
 
    }, 50*i); 
 
    })(i); 
 
}
body{background: #333;} 
 
.console-effect{color: #0f0; font-family: monospace; font-size: 2em;}
<div class="console-effect">This is some example text</div>

+0

ありがとう、私は今なぜ私はエラーを理解します。私が実際には得られなかったのは、setTimeoutの周りにクロージャを使用するのはなぜですか?私はあなたの答えを読むことを意味するが、私はまだそれを取得していない:/ –

+1

@ ShockE。あなたが「i」に何が起こるかを理解するのに役立つ2つの例がここにあります。クロージャなしのもの:https://jsfiddle.net/zyLozkvp/ご覧のとおり、ループが終了すると、グローバルスコープでは 'i'が' 11'になります。クロージャ付きのもの:https://jsfiddle.net/0L3oou1s/。今回は、クロージャ(関数)があるので、新しいスコープを作成しています。ここで、 'i'は全く新しい変数ですが、独自のスコープ内にあります。それはそれをより明確にするか? – blex

1

JavaScriptでループ内の関数を作るためには良い考えではない、私はそれで悪い経験をしました。この方法で行わ

このコードが正常に動作するはずです:

function type() { 
    var text = document.querySelector('.console-effect').textContent; 
    var loopFunc = function(i) { 
     return function() { 
      document.querySelector('.console-effect').textContent = text.substr(0, i) 
     }; 
    }; 
    for (var i = 0; i <= text.length; i++) { 
     setTimeout(loopFunc(i), 50); 
    } 
} 
type(); 
-2

は(50ミリ秒の遅延の後に、あなたのケースで)一度だけ実行したsetTimeout。彼らは各反復上で実行するためにforループが待たれていないため

この目的のためには、のsetInterval

+0

setIntervalは永遠にループします。 –

+0

あなたは望みどおりに多くの 'setTimeout'を持つことができます。それらはお互いに独立してスタックに置かれます。 – jered

+0

var index = 0; のsetInterval(関数(){ \tはconsole.log( '学習JS') \t場合(インデックス== 10){ \t \tてclearInterval(この); \t} インデックス++;} 、1000)。 –

0
var text = document.querySelector('.console-effect').textContent; 
var index = 0; 
setInterval(function(){ 
    document.querySelector('.console-effect').textContent = text.substr(0, index); 
    if(index == text.lenght){ 
     clearInterval(this); 
    } 
index++; 
},1000); 
0

このような何かを行います。

function type() { 
    var text = document.querySelector('.console-effect').textContent; 
    document.querySelector('.console-effect').textContent = '';//clear content 
    for (var i = 0; i <= text.length; i++) { 
     setTimeout(function(j) { 
      document.querySelector('.console-effect').textContent += text[j];// or .charAt(j) 
     }, 50 * i, i); 
     // 50 * i sets timeout for each iteration 
     // i (3rd arg) passes to the inner function 
    } 
} 
type(); 

function type(text) { 
    var textObj = document.querySelector('.console-effect'); 
    for (var i = 0; i <= text.length; i++) { 
     setTimeout(function(ch) { 
      textObj.textContent += ch; 
     }, 50 * i, text[i]); 
     // 50 * i sets timeout for each iteration 
     // i (3rd arg) passes to the inner function 
    } 
} 
type('.console-effect'); 
0

50 * iのないソリューションでも、CSS効果を見てください。あなたの問題は、setTimeoutメソッドは、(「制御フロー」は、それらの50msの間待たない)非同期に実行されているので、彼らは、値I = text.lengthで一斉に発射されている(あなたのテキストが十分に小さい場合)

<p class="console-effect">console effects</p> 
<script> 
function type() { 
     var i=0; 
     var t = document.querySelector('.console-effect').textContent; 
     var fn = setInterval(function() { 
      print_text(++i,t,fn) 
     }, 500); 
} 
function print_text(i,t,fn){ 
    if(i <= t.length){ 
       document.querySelector('.console-effect').textContent = t.substr(0, i) 
    } else clearInterval(fn) 
} 
type(); 

</script> 
<style> 
@-webkit-keyframes blinker { 
    from { opacity: 1.0; } 
    to { opacity: 0.0; } 
} 
.console-effect:after{ 
    content:'_'; 
    text-decoration: blink; 
    -webkit-animation-name: blinker; 
    -webkit-animation-duration: 0.2s; 
    -webkit-animation-iteration-count:infinite; 
    -webkit-animation-timing-function:ease-in-out; 
    -webkit-animation-direction: alternate; 
    } 
</style> 
1

私は@blexを信じたくなかったが、彼は範囲について正しいものだった。彼は、彼が作った両方の点で正しいですが、閉鎖は私を驚かせました。どのように私はこれに遭遇したことはありませんし、前に自分の道をパズルすることを余儀なくされている?

ここでのアイデアは、最初に数十回ほどあなたの関数の呼び出しをスケジュールするのではなく、次の呼び出しをスケジュールするということです。それを呼び出した後、次のスケジュールを設定する必要があるかどうかを確認します。

function type() { 
 
    var text = document.querySelector('.console-effect').textContent; 
 
    var i = 0; 
 
    var typeNext = function() { 
 
     ++i; 
 
     document.querySelector('.console-effect').textContent = text.substr(0, i); 
 
     if(i < text.length) { 
 
      setTimeout(typeNext, 50); 
 
     } 
 
    } 
 
    setTimeout(typeNext, 50); 
 
} 
 
type();
<span class="console-effect">This is a test</span>

+0

type()関数の最後にあるsetTimeoutは何を説明してくれますか?私はそれが最初にtypeNext()を呼び出すことが分かっている場合は? –

+0

@ ShockE。それは正しいです。関数を宣言した後、私は50ms遅れて呼び出します。次に、メソッドの最後に、遅延と呼び出しが必要かどうかを判断します。 – Nate

関連する問題