ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript トピック 3: 手ぶれ補正

JavaScript トピック 3: 手ぶれ補正

coldplay.xixi
coldplay.xixi転載
2021-03-04 09:56:003176ブラウズ

JavaScript トピック 3: 手ぶれ補正

#目次

    1. 手ぶれ補正が必要な理由
  • 2.手ぶれ補正の原理
  • 3. 手ぶれ補正の簡単な実装
  • 4. 高度な手ぶれ補正
  • #最後に書く
(関連する無料学習の推奨事項:

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 を見てください:

JavaScript トピック 3: 手ぶれ補正この例は非常に単純であるため、ブラウザは完全に応答できますが、次のように仮定します。頻度が高く、毎分 2000 回、位置計算、DOM 操作などが多く発生します

インターフェースリクエストがあり、単一関数の実行時間は長いですが、各関数のトリガー間隔はとても近い。

  • この種のインタラクションは、ブラウザやサーバーに瞬間的 (短期間) に多大な負荷をかけるため、最適化する必要があります。この問題を解決するには、一般に 2 つの解決策があります。 :
  • デバウンス アンチシェイク

スロットル スロットリング

  • その目的は次のとおりです:
  • 関数のトリガー頻度を減らして、パフォーマンスを向上させるか回避します。資源の無駄遣い。

2. 手ぶれ補正の原理

今日は手ぶれ補正の実装に焦点を当てます。

手ぶれ補正の原理は次のとおりです。イベントをトリガーした場合でも、イベントがトリガーされてから n 秒間非アクティブ状態が続いた場合にのみイベントが実行されます。例:

手ぶれ補正の標準として

3 秒

を規定すると、次のようになります:

初めてイベントが要求されたとき - カウントダウンは 3 秒

この時点では カウントダウン 2 秒 #カウントダウン 1 秒

    イベントは 0.5 秒で再びトリガーされます - 今度はカウントダウン 3 秒
  1. ...3 秒以内は何も起こりません
  2. 実行 イベントにかかった時間は 5.5 秒
  3. #3. 手ぶれ補正を自分で実装する
  4. # 3.1 初版

前のセクションで説明した中心的なアイデアに基づいてコードの最初のバージョンを実装します。 JavaScript トピック 3: 手ぶれ補正

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);
    }}

を見てみましょう。結局のところ、匿名関数の層によってラップされています。これはすでに指しています。影響を軽減するために、修正を試みますJavaScript トピック 3: 手ぶれ補正

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。高度な手ぶれ補正

4.1 即時実行

この要件は次のとおりです:JavaScript トピック 3: 手ぶれ補正

即時実行Keep

n

秒の空白期間

n
    2 番目の空白期間を後ろに置きます
  • この要件について考えるのは理にかなっています。次に、immediate を追加しましょう。パラメータは、すぐに実行するかどうかを決定します。
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 トピック 3: 手ぶれ補正

    Write この単純な手ぶれ補正方法がOKだとしても、完璧ではありません。改善点がある場合は、コメント欄にメッセージを残してください~

    関連する無料学習の推奨事項: javascript (ビデオ)

    以上がJavaScript トピック 3: 手ぶれ補正の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事はcsdn.netで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。