2017-10-19 18 views
0

私はここで狂っています。 マウスの移動に要素を表示し、マウスの最後の移動から10秒後に要素を非表示にしたい。無限ループwhile mousemove

私はこれを書いた:

document.addEventListener("DOMContentLoaded", function(event) { 
    var time = 0; 
    document.addEventListener("mousemove", function(event) { 
    console.log('$'); 
    document.getElementsByClassName("mybar")[0].style.visibility = 'visible'; 
    time = 0; 
    while (time < 11) { 
     setTimeout(function() { 
     time++ 
     }, 1000); 
     console.log(time, time == 10); 
     if (time == 10) { 
     document.getElementsByClassName("mybar")[0].style.visibility = 'hidden'; 
     } 
    } 
    }); 
}); 
<div class='mybar'> 
    <h1> TESTING </h1> 
</div> 

なぜそれが無限ループで終わるんか? なぜそれは状態で終了しないのですか?どうしてifは本当のパラメータを決して得られないのでしょうか? 通知:この方法で実行しないでください...あなたのタブを削除します。

+0

あなたの目標は、ここでは何ですか?マウスがウィンドウ内を移動するたびにdivを10秒間表示しようとしていますか? – Turk

+0

あなたは 'while'は必要ありません。 'setTimeout'はあなたのためのすべてのタイミングを行います。'n'ミリ秒後に何を呼び出すべきかを伝えるだけです。 – zero298

+3

です。setTimeoutは非同期です。 – epascarello

答えて

2

まず、あなたがやったならば、あなたは最初の場所でDOMContentLoadedを追加することができなかったため、documentにイベントリスナーを追加するDOMContentLoadedのを待つ必要はありません。

setTimeoutがスクリプトを一時停止しないため、無限ループが発生します。指定した時刻にコールバックをスケジュールし、その時刻に関係なくは、time変数をインクリメントしないため、スレッド内の現在実行中のコードが完了するまでを実行しません。

ループが終了することはないため、スレッドは決して利用できないため、コールバックは実行されないため、timeは決してインクリメントできません。

最後に、ローカル変数を共有し、mousemoveのようなイベントで非常に高速に実行するイベントハンドラ内でsetTimeoutを開始すると、予期しない結果が発生しやすくなります。たとえば、あなたのコードでは、ハンドラが実行されるたびにtime0にリセットされます。これはあなたが望むものではないようです。


溶液は、ループを捨て10秒間可視性をスケジュールし、ブール変数を使用して、その間に実行してから、ハンドラ内のコードの主要な部分を防止することであろう。

var timer = null; 
document.addEventListener("mousemove", function(event) { 
    var myBar = document.querySelector(".mybar"); 
    if (!myBar) { 
     return; // there's no mybar element 
    } 


    if (timer == null) { 
     myBar.style.visibility = 'visible'; 
    } else { 
     clearTimeout(timer); // clear the currently running timer 
    } 

    // set to hidden in 10 seconds 
    timer = setTimeout(function() { 
     myBar.style.visibility = 'hidden'; 
     timer = null; // clear the timer 
    }, 10000); 
}); 

それは短く、きれいだから、私もquerySelector代わりのgetElementsByClassNameに切り替えます。そして、スタイルを設定する前に要素が見つかったことを確認するために変数を使用しました。

+0

ありがとうございます。それは私が最初に書いたものと非常に似ています。 コード通りに機能しました。このような唯一の問題は、最初の移動から10秒後にバーが消えてしまうことです...マウスが動いたとしても。 – matisa

+1

@matisa:* last * mousemoveの10秒後に消えたい場合は、タイムアウトをクリアしてそのようなイベントが発生するたびに新しいものを開始する必要があります。この例を更新します。 – llama

0

すでに実行したことをリスナーに伝えるmousemoveスコープの外にフラグが必要です。文脈では

if(running) return; 
running = true; 

document.addEventListener("DOMContentLoaded", function(event) { 
    var time = 0; 
    var running = false; 
    document.addEventListener("mousemove", function(event) { 

    console.log('$'); 

    if(running) return; 
    running = true; 

    document.getElementsByClassName("mybar")[0].style.visibility = 'visible'; 
    time = 0; 
    while (time < 11) { 
     setTimeout(function() { 
     time++ 
     }, 1000); 
     console.log(time, time == 10); 
     if (time == 10) { 
     document.getElementsByClassName("mybar")[0].style.visibility = 'hidden'; 
     } 
    } 
    }); 
}); 
+0

しかし、この場合は1回だけ実行されます。 これはプレーヤーをビルドしています。 マウスが動いてから10秒後にコントロールバーを消したいのですが。新しい動きで、私は再び登場する必要があります。 – matisa

0

ここでは通常のJavaScriptでそれを行う方法です。ブラウザがES6に準拠していない場合は、矢印関数を正規関数式に置き換えることができます。この例では、10秒ではなく2秒後にテキストが非表示になります。余分な秒数を無駄にすることなく動作することがわかります。

//hide by default 
 
document.getElementById('myBar').style.display = 'none'; 
 

 
var timer = null; 
 

 
var hideDivTimer =() => { 
 
    timer = setTimeout(() => { 
 
    document.getElementById('myBar').style.display = 'none'; 
 
    }, 2000); 
 
}; 
 

 
document.addEventListener('mousemove',() => { 
 
    clearTimeout(timer); 
 
    document.getElementById('myBar').style.display = 'inline'; 
 
    hideDivTimer(); 
 
});
<body> 
 
    <div id='myBar'> 
 
    <h1> TESTING </h1> 
 
    </div> 
 
</body>

関連する問題