ホームページ > 記事 > ウェブフロントエンド > JavaScript トピック 3: 手ぶれ補正
#目次
JavaScript ビデオ チュートリアル #)
1.手ぶれ補正が必要な理由高頻度の関数操作は悪影響を及ぼす可能性があります
index.html ファイルを作成します。
<meta> <meta> <meta> <title>Document</title> <title>debounce</title> <style> #wrapper { width: 100%; height: 200px; line-height: 200px; text-align: center; color: #fff; background-color: #444; font-size: 30px; } </style> <p></p> <script> var count = 1; var op = document.getElementById("wrapper"); function getUserAction() { op.innerHTML = count++; } op.onmousemove = getUserAction; </script>
これはトリガーします。左から右にスライドすると
getUserAction 関数を 100 回近く実行します。次の Gif を見てください:
この例は非常に単純であるため、ブラウザは完全に応答できますが、次のように仮定します。頻度が高く、毎分 2000 回、位置計算、DOM 操作などが多く発生します
インターフェースリクエストがあり、単一関数の実行時間は長いですが、各関数のトリガー間隔はとても近い。
スロットル スロットリング
2. 手ぶれ補正の原理
今日は手ぶれ補正の実装に焦点を当てます。手ぶれ補正の原理は次のとおりです。イベントをトリガーした場合でも、イベントがトリガーされてから n 秒間非アクティブ状態が続いた場合にのみイベントが実行されます。例:
手ぶれ補正の標準として
3 秒 を規定すると、次のようになります:
この時点では カウントダウン 2 秒
#カウントダウン 1 秒
前のセクションで説明した中心的なアイデアに基づいてコードの最初のバージョンを実装します。
function debounce(func, wait) { var timer; return function () { clearTimeout(timer) timer = setTimeout(func, wait); }}これを使用する場合は、最初のセクションの例を次のように取り上げます。例:
op.onmousemove = debounce(getUserAction, 2000);At this time You can test it again. イベントが発生し続ける場合、イベントは完全に停止してから 2 秒後にのみトリガーされます: ここに書かれているように、一部の高頻度イベントの要件は終了しました。その効果を見てみましょう:
3.2 Second Edition
ご存知のとおり、dom ノードがイベントをトリガーすると、これはそれ自体を指します。この例では、
opを指していますが、この場合:
var count = 1;var op = document.getElementById("op");function getUserAction() { op.innerHTML = count++; console.log('this', this); // 此时输出 Window...}op.onmousemove = debounce(getUserAction, 2000);function debounce(func, wait) { var timer; return function () { clearTimeout(timer) timer = setTimeout(func, wait); }}
を見てみましょう。結局のところ、匿名関数の層によってラップされています。これはすでに指しています。影響を軽減するために、修正を試みます
function debounce(func, wait) { var timer; return function () { var _this = this; // 记录当前this clearTimeout(timer) timer = setTimeout(function(){ func.apply(_this); //将 func的this改为_this }, wait); }}第3版この指摘の問題は解決しましたが、私たちの関数はまだ十分に「完璧」ではありません。イベント処理関数は
event オブジェクトを提供します。これを略して e と呼びます。
// 使用了 debouce 函数function getUserAction(e) { console.log(e); // undefined op.innerHTML = count++;};信頼性を確保するために、3 番目のバージョンを変更します:
var count = 1;var op = document.getElementById("op");function getUserAction(e) { op.innerHTML = count++; console.log('e', e); // MouseEvent}op.onmousemove = debounce(getUserAction, 2000);function debounce(func, wait) { var timer; return function () { var _this = this; // 记录当前this var arg = arguments; // 记录参数 clearTimeout(timer) timer = setTimeout(function () { func.apply(_this, arg); //将 func的this改为_this }, wait); }}これまでのところ、Dom イベントの元の機能をできる限り維持しながら機能を追加してきました。 . 手ぶれ補正効果を使用すると、日常の開発における手ぶれ補正の問題のほとんどを解決できますが、より「完璧」である必要があります
4.1 即時実行
この要件は次のとおりです:
即時実行Keep
nimmediate
を追加しましょう。パラメータは、すぐに実行するかどうかを決定します。 function debounce(func, wait, immediate) { var timer; return function () { var _this = this; var args = arguments; if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时 if (immediate) { // 如果已经执行过,不再执行 var callNow = !timer; // 1. callNow 初始值是 true, 同步立即执行;随后 timer 才开始执行 timer = setTimeout(function(){ timer = null; // wait 期间,timer 是一个 ID 数字,所以 callNow 为 false,func 在此期间永远不会执行 }, wait) // wait 之后,timer 赋值 null,callNow 为 true,func 又开始立即执行。 if (callNow) func.apply(_this, args) } else { timer = setTimeout(function(){ func.apply(_this, args) }, wait); } }}
4.2 簡単な検証を追加します<pre class="brush:php;toolbar:false">function debounce(func, wait, immediate) {
var timer;
// 检查函数
if (typeof func !== 'function') {
throw new TypeError('Expected a function');
}
// 保证wait存在
wait = +wait || 0;
const debounced = function () {
var _this = this;
var args = arguments;
if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时
if (immediate) {
// 如果已经执行过,不再执行
var callNow = !timer; // 如果不存在定时器,则callNow为true
timer = setTimeout(function () {
timer = null; // 为了保证之后的时效性,手动添加timer
}, wait)
// 因为不存在timer,证明是首次执行,所以直接调用
if (callNow) func.apply(_this, args)
}
else {
timer = setTimeout(function () {
func.apply(_this, args)
}, wait);
}
}
return debounced}</pre>
4.3 キャンセル イベント メソッドを追加します
手ぶれ補正イベントをキャンセルしたい場合は、次のように記述できます:
function debounce(func, wait, immediate) { var timer; // 检查函数 if (typeof func !== 'function') { throw new TypeError('Expected a function'); } // 保证wait存在 wait = +wait || 0; const debounced = function () { var _this = this; var args = arguments; if (timer) clearTimeout(timer); // 常规流程,间隔内触发时清掉重置定时 if (immediate) { // 如果已经执行过,不再执行 var callNow = !timer; // 如果不存在定时器,则callNow为true timer = setTimeout(function () { timer = null; // 为了保证之后的时效性,手动添加timer }, wait) // 因为不存在timer,证明是首次执行,所以直接调用 if (callNow) func.apply(_this, args) } else { timer = setTimeout(function () { func.apply(_this, args) }, wait); } } const cancel = function(){ clearTimeout(timer); timer = null; } const pending = function(){ return timer !== undefined; } debounced.cancel = cancel; debounced.pending = pending; return debounced}
効果を見てみましょう:
関連する無料学習の推奨事項: javascript (ビデオ)
以上がJavaScript トピック 3: 手ぶれ補正の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。