2017-06-25 27 views
1

ページを特定の要素にスクロールした後、その要素にクラスを追加する必要があります。問題は、完全な関数がスクロールアニメーションの完了前に起動するため、間違った要素がクラスを取得することです。私はsetTimeout()で完全な関数をラップするとうまくいきます。jQuery animate()の完了関数は完了前に起動します

なぜ完全な機能が完了する前に起動しますか?それは既知の問題ですか?この問題を解決する最も信頼できる方法は何ですか?

マイコード:

$('html, body').animate({ 
    scrollTop: current_element_position + 'px' 
}, 'fast', function(){ 
    current_element.addClass('current_element'); 
}); 
+1

ここで確認することができますあなたは、アニメーション機能のための高速な引数を書きました。ここでは、高速、中、低の3つのオプションがあります。したがって、それぞれには効果を完了するための一定の時間があります。しかし、JavaScriptは非同期であるため、次のアクションの開始を待つことはありません。 1つのアクションが実行時間よりも時間がかかる場合、次のコードは実行を開始します。 –

+1

あなたが言うことが正しければ、なぜ彼らはhttp://api.jquery.com/animate/で完全な機能を「完全」と呼んだのですか?関数が実際に完了する前に起動するケースがある場合、その用語はかなり誤解を招くようです。 – drake035

+0

あなたは正しいです。しかし、あなたはこれを考慮する必要があり、あなたが言ったように、タイムアウトを設定するとあなたに役立つだろう。 –

答えて

2

に役立ちます。つまり、アニメーションは実際には2回実行され、完全な関数も2回呼び出されます。

これが正常に行われる理由は、一部のブラウザではスクロールのみがサポートされているため、htmlとスクロールのみがサポートされているのはbodyです。このセレクタは両方を対象にしていますが、この問題を解決するだけでなく、このダブルアニメーション呼び出しも発生します。

実際にスクロールしないアニメーションははるかに速く完了します。したがって、他の要素の実際のアニメーションが完了する前に完全な呼び出しをトリガします。

これを知ることで、余分な変数を設定することで回避できます。これにより、コードは前回の呼び出しでのみ実行されます。

var isComplete = false; 
$('html, body').animate({ 
    scrollTop: current_element_position + 'px' 
}, 'fast', function() { 
    if (isComplete) { 
    current_element.addClass('current_element'); 
    isComplete = false; 
    } 
    else { 
    isComplete = true; 
    } 
}); 

さらに簡単に言えば、約束してください。

$('html, body') 
    .animate({ scrollTop: current_element_position + 'px' }, 'fast') 
    .promise() 
    .then(function() { 
    current_element.addClass('current_element'); 
    }); 
0

私はあなたのHTMLがどのように見えるのか分かりません。それにもかかわらず、私はあなたの意図を持っていて、jQueryやアニメーションなしでやっている別のアプローチを試して欲しいと思います。基本的に、ページがスクロールされている間、要素のトップが特定の範囲内にあるかどうかをチェックします。 htmlbody:多分それはあなたが2つの要素にアニメーション効果を呼び出している...

var divs = document.querySelectorAll('.testdiv'); 
 
window.onscroll = function() { 
 
    divs.forEach(function(item) { 
 
    var top = item.getBoundingClientRect().top; 
 
    item.style.background = 'transparent'; 
 
    if (top >= 70 && top <= 140) { 
 
     item.style.background = 'red'; 
 
    } 
 
    }); 
 
}
.testdiv{ 
 
    width: 200px; 
 
    height: 70px; 
 
    border: 1px solid black; 
 
} 
 
.testdiv:first-of-type{ 
 
    margin-top: 100px; 
 
}
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div> 
 
<div class="testdiv"></div>

0

表示する要素にスクロールするクラスを追加する場合は、以下のコードを試してください。

$(function() { 
 
    /** 
 
\t jQuery Custom method to find if element is in View 
 
*/ 
 
    $.fn.isInView = function() { 
 
    if (!this.length) return false; 
 
    var rect = this.get(0).getBoundingClientRect(); 
 
    return (
 
     rect.top >= 0 && 
 
     rect.left >= 0 && 
 
     rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && 
 
     rect.right <= (window.innerWidth || document.documentElement.clientWidth) 
 
    ); 
 

 
    }; 
 
    /** 
 
\t Window Scroll Event: 
 
*/ 
 
    $(window).on('scroll', function(e) { 
 
    var $this = $(this); 
 
    /** 
 
     Trigger Custom Event on timeout if Scroll is stopped else clear the timeout 
 
     */ 
 
    clearTimeout($this.data('scrollTimeout')); 
 
    $this.data('scrollTimeout', setTimeout(function() { 
 
     $(window).trigger('scrollStop') 
 
    }, 50, e)); 
 
    }); 
 

 
    /** 
 
     On ScrollStop Loop Through Each Element and check if it is in view, If yes add Class else remove Class 
 
     */ 
 
    $(window).on('scrollStop', function(ev) { 
 
    $('div').each(function() { 
 
     var $div = $(this) 
 
     if ($div.isInView()) { 
 
     $div.addClass('color'); 
 
     } else { 
 
     $div.removeClass('color'); 
 
     } 
 
    }); 
 
    }).trigger('scrollStop'); 
 
});
div { 
 
    width: 100%; 
 
    height: 170px; 
 
    border: 1px solid black; 
 
} 
 

 
.color { 
 
    background: red; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div> 
 
<div></div>

0

**あなたは** はそれが動作するはずこれを試して、ウィンドウのスクロールプロパティを使用することができます。 divにスクロールするとクラスが追加され、再び上に移動するとクラスが削除されます。 あなたがhttps://jsfiddle.net/surendra786/qnhw5ov7/

html -- 
<p class="new"></div> 

script --- 

$('document').ready(function(){ 
    var current_element=$('.new'); 
    var current_element_position = $('.new').position().top; 

    $(window).scroll(function() {  
    var scroll = $(window).scrollTop(); 
    current_element.toggleClass('current_element', 
    scroll >= current_element_position 
); 

    }); 
}); 
関連する問題