AJAX経由で要素をロードしています。それらのいくつかは、ページを下にスクロールしないと表示されません。要素がページの表示部分にあるかどうかを知る方法はありますか?
46 に答える
これでうまくいくはずです:
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
シンプルなユーティリティ関数 これにより、探している要素を受け入れるユーティリティ関数を呼び出すことができ、要素を完全に表示するか部分的に表示するかを指定できます。
function Utils() {
}
Utils.prototype = {
constructor: Utils,
isElementInView: function (element, fullyInView) {
var pageTop = $(window).scrollTop();
var pageBottom = pageTop + $(window).height();
var elementTop = $(element).offset().top;
var elementBottom = elementTop + $(element).height();
if (fullyInView === true) {
return ((pageTop < elementTop) && (pageBottom > elementBottom));
} else {
return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
}
}
};
var Utils = new Utils();
使用法
var isElementInView = Utils.isElementInView($('#flyout-left-container'), false);
if (isElementInView) {
console.log('in view');
} else {
console.log('out of view');
}
バニラでのこの回答:
function isScrolledIntoView(el) {
var rect = el.getBoundingClientRect();
var elemTop = rect.top;
var elemBottom = rect.bottom;
// Only completely visible elements return true:
var isVisible = (elemTop >= 0) && (elemBottom <= window.innerHeight);
// Partially visible elements return true:
//isVisible = elemTop < window.innerHeight && elemBottom >= 0;
return isVisible;
}
これまでに見つけた最良の方法は、jQuery appear pluginです。魅力のように機能します。
カスタムの「appear」イベントを模倣します。このイベントは、要素がスクロールして表示されるか、ユーザーに表示されるようになったときに発生します。
$('#foo').appear(function() { $(this).text('Hello world'); });
このプラグインを使用すると、非表示または表示可能領域外のコンテンツに対する不要なリクエストを防ぐことができます。
jQuery Waypoints プラグインは、ここで非常にうまく機能します。
$('.entry').waypoint(function() {
alert('You have scrolled to an entry.');
});
プラグインのサイトにいくつかの例があります。
どうですか
function isInView(elem){
return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;
}
その後、このように要素が表示されたら、必要なものをトリガーできます
$(window).scroll(function(){
if (isInView($('.classOfDivToCheck')))
//fire whatever you what
dothis();
})
それは私にとってはうまくいきます
私の要件に合わせて Scott Dowding のクールな機能を Tweeked しました。
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}
WebResourcesDepotは、しばらく前にjQueryを使用してスクロール中にロードするスクリプトを作成しました。ここでライブデモを見ることができます。それらの機能の牛肉はこれでした:
$(window).scroll(function(){
if ($(window).scrollTop() == $(document).height() - $(window).height()){
lastAddedLiveFunc();
}
});
function lastAddedLiveFunc() {
$('div#lastPostsLoader').html('<img src="images/bigLoader.gif">');
$.post("default.asp?action=getLastPosts&lastPostID="+$(".wrdLatest:last").attr("id"),
function(data){
if (data != "") {
$(".wrdLatest:last").after(data);
}
$('div#lastPostsLoader').empty();
});
};
ここでのほとんどの回答では、ページ全体だけでなく、div のビューからスクロールされるため、要素も非表示になる可能性があることを考慮していません。
その可能性をカバーするには、基本的に、要素が各親の境界内に配置されているかどうかを確認する必要があります。
このソリューションはまさにそれを行います:
function(element, percentX, percentY){
var tolerance = 0.01; //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimals
if(percentX == null){
percentX = 100;
}
if(percentY == null){
percentY = 100;
}
var elementRect = element.getBoundingClientRect();
var parentRects = [];
while(element.parentElement != null){
parentRects.push(element.parentElement.getBoundingClientRect());
element = element.parentElement;
}
var visibleInAllParents = parentRects.every(function(parentRect){
var visiblePixelX = Math.min(elementRect.right, parentRect.right) - Math.max(elementRect.left, parentRect.left);
var visiblePixelY = Math.min(elementRect.bottom, parentRect.bottom) - Math.max(elementRect.top, parentRect.top);
var visiblePercentageX = visiblePixelX / elementRect.width * 100;
var visiblePercentageY = visiblePixelY / elementRect.height * 100;
return visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY;
});
return visibleInAllParents;
};
また、各方向に表示するパーセンテージを指定することもできます。
などの他の要因により非表示になっている可能性はありませんdisplay: hidden
。
のみを使用するため、これはすべての主要なブラウザーで機能するはずgetBoundingClientRect
です。Chrome と Internet Explorer 11 で個人的にテストしました。
これは、ビューポート自体よりも大きい要素だけでなく、要素が持つパディング、ボーダー、またはマージンも考慮します。
function inViewport($ele) {
var lBound = $(window).scrollTop(),
uBound = lBound + $(window).height(),
top = $ele.offset().top,
bottom = top + $ele.outerHeight(true);
return (top > lBound && top < uBound)
|| (bottom > lBound && bottom < uBound)
|| (lBound >= top && lBound <= bottom)
|| (uBound >= top && uBound <= bottom);
}
それを呼び出すには、次のようなものを使用します。
var $myElement = $('#my-element'),
canUserSeeIt = inViewport($myElement);
console.log(canUserSeeIt); // true, if element is visible; false otherwise
新しい「inview」イベントを追加する、inviewと呼ばれる jQuery 用のプラグインがあります。
イベントを使用しない jQuery プラグインのコードを次に示します。
$.extend($.expr[':'],{
inView: function(a) {
var st = (document.documentElement.scrollTop || document.body.scrollTop),
ot = $(a).offset().top,
wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
return ot > st && ($(a).height() + ot) < (st + wh);
}
});
(function( $ ) {
$.fn.inView = function() {
var st = (document.documentElement.scrollTop || document.body.scrollTop),
ot = $(this).offset().top,
wh = (window.innerHeight && window.innerHeight < $(window).height()) ? window.innerHeight : $(window).height();
return ot > st && ($(this).height() + ot) < (st + wh);
};
})( jQuery );
これは、 James という男によるコメント ( http://remysharp.com/2009/01/26/element-in-view-event-plugin/ ) で見つかりました。
スクロール可能な DIV コンテナー内の要素の可視性を確認する必要がありました
//p = DIV container scrollable
//e = element
function visible_in_container(p, e) {
var z = p.getBoundingClientRect();
var r = e.getBoundingClientRect();
// Check style visiblilty and off-limits
return e.style.opacity > 0 && e.style.display !== 'none' &&
e.style.visibility !== 'hidden' &&
!(r.top > z.bottom || r.bottom < z.top ||
r.left > z.right || r.right < z.left);
}
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop(),
docViewBottom = docViewTop + $(window).height(),
elemTop = $(elem).offset().top,
elemBottom = elemTop + $(elem).height();
//Is more than half of the element visible
return ((elemTop + ((elemBottom - elemTop)/2)) >= docViewTop && ((elemTop + ((elemBottom - elemTop)/2)) <= docViewBottom));
}
この回答に基づいて、要素が 75% 表示されているかどうかを確認する例 (つまり、25% 未満が画面から外れている)。
function isScrolledIntoView(el) {
// check for 75% visible
var percentVisible = 0.75;
var elemTop = el.getBoundingClientRect().top;
var elemBottom = el.getBoundingClientRect().bottom;
var elemHeight = el.getBoundingClientRect().height;
var overhang = elemHeight * (1 - percentVisible);
var isVisible = (elemTop >= -overhang) && (elemBottom <= window.innerHeight + overhang);
return isVisible;
}
別のdiv内でアイテムをスクロールするためにこれを微調整したい場合は、
function isScrolledIntoView (elem, divID)
{
var docViewTop = $('#' + divID).scrollTop();
var docViewBottom = docViewTop + $('#' + divID).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
}
アプリケーションにそのようなメソッドがありますが、jQuery を使用していません。
/* Get the TOP position of a given element. */
function getPositionTop(element){
var offset = 0;
while(element) {
offset += element["offsetTop"];
element = element.offsetParent;
}
return offset;
}
/* Is a given element is visible or not? */
function isElementVisible(eltId) {
var elt = document.getElementById(eltId);
if (!elt) {
// Element not found.
return false;
}
// Get the top and bottom position of the given element.
var posTop = getPositionTop(elt);
var posBottom = posTop + elt.offsetHeight;
// Get the top and bottom position of the *visible* part of the window.
var visibleTop = document.body.scrollTop;
var visibleBottom = visibleTop + document.documentElement.offsetHeight;
return ((posBottom >= visibleTop) && (posTop <= visibleBottom));
}
編集:この方法はIE(少なくともバージョン6)でうまく機能します。FF との互換性については、コメントをお読みください。
私はjQuery exprを使用することを好みます
jQuery.extend(jQuery.expr[':'], {
inview: function (elem) {
var t = $(elem);
var offset = t.offset();
var win = $(window);
var winST = win.scrollTop();
var elHeight = t.outerHeight(true);
if ( offset.top > winST - elHeight && offset.top < winST + elHeight + win.height()) {
return true;
}
return false;
}
});
こんな風に使えるので
$(".my-elem:inview"); //returns only element that is in view
$(".my-elem").is(":inview"); //check if element is in view
$(".my-elem:inview").length; //check how many elements are in view
このようなコードをscroll
イベント関数などに簡単に追加して、ユーザーがビューをスクロールするたびにチェックすることができます。
この質問には 30 以上の回答がありますが、どれも私が使用してきた驚くほどシンプルで純粋な JS ソリューションを使用していません。他の多くの人が推進しているように、これを解決するためだけに jQuery をロードする必要はありません。
要素がビューポート内にあるかどうかを判断するには、まず本体内の要素の位置を決定する必要があります。私がかつて考えていたように、これを再帰的に行う必要はありません。代わりに、 を使用できますelement.getBoundingClientRect()
。
pos = elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top;
この値は、オブジェクトの上部とボディの上部の Y 差です。
次に、要素がビュー内にあるかどうかを判断する必要があります。ほとんどの実装では、要素全体がビューポート内にあるかどうかを尋ねられるため、これについて説明します。
まず、ウィンドウの一番上の位置は次のとおりwindow.scrollY
です。
ウィンドウの高さを上部の位置に追加することで、ウィンドウの下部の位置を取得できます。
var window_bottom_position = window.scrollY + window.innerHeight;
要素の上部の位置を取得するための単純な関数を作成しましょう:
function getElementWindowTop(elem){
return elem && typeof elem.getBoundingClientRect === 'function' ? elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top : 0;
}
この関数は、ウィンドウ内の要素のトップ位置を返す0
か、メソッドで要素以外のものを渡すと返されます.getBoundingClientRect()
。この方法は昔からあるので、ブラウザがサポートしていないことを心配する必要はありません。
今、私たちの要素の最上位の位置は次のとおりです。
var element_top_position = getElementWindowTop(element);
And or 要素の一番下の位置は次のとおりです。
var element_bottom_position = element_top_position + element.clientHeight;
これで、要素の下部の位置がビューポートの上部の位置よりも低いかどうかを確認し、要素の上部の位置がビューポートの下部の位置よりも高いかどうかを確認することで、要素がビューポート内にあるかどうかを判断できます。
if(element_bottom_position >= window.scrollY
&& element_top_position <= window_bottom_position){
//element is in view
else
//element is not in view
そこから、in-view
要素のクラスを追加または削除するロジックを実行できます。これは、後で CSS のトランジション効果で処理できます。
この解決策が他に見つからなかったことに本当に驚いていますが、これが最もクリーンで最も効果的な解決策であり、jQuery をロードする必要がないと確信しています!
受け入れられた回答を変更して、要素の表示プロパティを「なし」以外に設定して品質を表示する必要があるようにしました。
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
var elemDisplayNotNone = $(elem).css("display") !== "none";
return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop) && elemDisplayNotNone);
}
要素の一部がページに表示されている場合、このメソッドは true を返します。私の場合はうまく機能し、他の人を助けるかもしれません。
function isOnScreen(element) {
var elementOffsetTop = element.offset().top;
var elementHeight = element.height();
var screenScrollTop = $(window).scrollTop();
var screenHeight = $(window).height();
var scrollIsAboveElement = elementOffsetTop + elementHeight - screenScrollTop >= 0;
var elementIsVisibleOnScreen = screenScrollTop + screenHeight - elementOffsetTop >= 0;
return scrollIsAboveElement && elementIsVisibleOnScreen;
}
要素がすぐに表示されるかどうかを確認する方法を探していたので、上記のスニペットを拡張することでそれを行うことができました。それが誰かを助ける場合に備えて、私はこれをここに残すと思った
elm = ビュー内にあることを確認する要素です
scrollElement = windowまたはスクロールを持つ親要素を渡すことができます
オフセット = 要素が画面に表示される前に 200 ピクセル離れたときに起動する場合は、200 を渡します。
function isScrolledIntoView(elem, scrollElement, offset)
{
var $elem = $(elem);
var $window = $(scrollElement);
var docViewTop = $window.scrollTop();
var docViewBottom = docViewTop + $window.height();
var elemTop = $elem.offset().top;
var elemBottom = elemTop + $elem.height();
return (((elemBottom+offset) >= docViewBottom) && ((elemTop-offset) <= docViewTop)) || (((elemBottom-offset) <= docViewBottom) && ((elemTop+offset) >= docViewTop));
}
多数の要素を非常に高速に処理するように設計されたタスク用のコンポーネントを作成しました (低速のモバイルで 1000 要素に対して 10 ミリ秒未満の調整まで)。
ウィンドウ、HTML 要素、埋め込まれた iframe、生成された子ウィンドウなど、アクセスできるすべてのタイプのスクロール コンテナーで動作し、検出する内容が非常に柔軟です (完全または部分的な可視性、ボーダー ボックスまたはコンテンツ ボックス、カスタム許容範囲など)。 )。
大部分が自動生成された大規模なテスト スイートにより、宣伝されているクロスブラウザーとして動作することが保証されます。
必要に応じて試してみてください: jQuery.isInView。それ以外の場合は、ソース コード (例:ここ) でインスピレーションを見つけることができます。
スクロール可能なdiv(コンテナ)の簡単な修正
var isScrolledIntoView = function(elem, container) {
var containerHeight = $(container).height();
var elemTop = $(elem).position().top;
var elemBottom = elemTop + $(elem).height();
return (elemBottom > 0 && elemTop < containerHeight);
}
注: 要素がスクロール可能な div よりも大きい場合、これは機能しません。
これをスクリプトと組み合わせて div を移動し、常に表示されるようにしたことを共有したかっただけです。
$("#accordion").on('click', '.subLink', function(){
var url = $(this).attr('src');
updateFrame(url);
scrollIntoView();
});
$(window).scroll(function(){
changePos();
});
function scrollIntoView()
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $("#divPos").offset().top;
var elemBottom = elemTop + $("#divPos").height();
if (elemTop < docViewTop){
$("#divPos").offset({top:docViewTop});
}
}
function changePos(){
var scrTop = $(window).scrollTop();
var frmHeight = $("#divPos").height()
if ((scrTop < 200) || (frmHeight > 800)){
$("#divPos").attr("style","position:absolute;");
}else{
$("#divPos").attr("style","position:fixed;top:5px;");
}
}
div が完全に画面上にあるかどうかを確認する受け入れられた回答のアプローチではなく、要素が画面上にあるかどうかを確認します (div が画面よりも大きい場合は機能しません)。純粋な Javascript の場合:
/**
* Checks if element is on the screen (Y axis only), returning true
* even if the element is only partially on screen.
*
* @param element
* @returns {boolean}
*/
function isOnScreenY(element) {
var screen_top_position = window.scrollY;
var screen_bottom_position = screen_top_position + window.innerHeight;
var element_top_position = element.offsetTop;
var element_bottom_position = element_top_position + element.offsetHeight;
return (inRange(element_top_position, screen_top_position, screen_bottom_position)
|| inRange(element_bottom_position, screen_top_position, screen_bottom_position));
}
/**
* Checks if x is in range (in-between) the
* value of a and b (in that order). Also returns true
* if equal to either value.
*
* @param x
* @param a
* @param b
* @returns {boolean}
*/
function inRange(x, a, b) {
return (x >= a && x <= b);
}
これを行うために一貫して機能する唯一のプラグインは、https ://github.com/customd/jquery-visible です。
プラグインを使用するためだけに jquery を依存関係として追加したくなかったので、最近このプラグインをGWTに移植しました。これが私の(単純な)ポートです(私のユースケースに必要な機能だけを含んでいます):
public static boolean isVisible(Element e)
{
//vp = viewPort, b = bottom, l = left, t = top, r = right
int vpWidth = Window.getClientWidth();
int vpHeight = Window.getClientHeight();
boolean tViz = ( e.getAbsoluteTop() >= 0 && e.getAbsoluteTop()< vpHeight);
boolean bViz = (e.getAbsoluteBottom() > 0 && e.getAbsoluteBottom() <= vpHeight);
boolean lViz = (e.getAbsoluteLeft() >= 0 && e.getAbsoluteLeft() < vpWidth);
boolean rViz = (e.getAbsoluteRight() > 0 && e.getAbsoluteRight() <= vpWidth);
boolean vVisible = tViz && bViz;
boolean hVisible = lViz && rViz;
return hVisible && vVisible;
}
Javascriptのみ:)
function isInViewport(element) {
var rect = element.getBoundingClientRect();
var html = document.documentElement;
return (
rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || html.clientHeight) &&
rect.right <= (window.innerWidth || html.clientWidth)
);
}