Làm thế nào để kiểm tra nếu phần tử được hiển thị sau khi cuộn?


1170

Tôi đang tải các phần tử thông qua AJAX. Một số trong số chúng chỉ hiển thị nếu bạn cuộn xuống trang.
Có cách nào tôi có thể biết nếu một phần tử hiện đang ở phần hiển thị của trang không?


42
anh ta có nghĩa là anh ta muốn một phương thức để biết liệu một phần tử đã cho có được hiển thị trong cửa sổ trình duyệt hay không, nếu người dùng cần cuộn để xem nó.
Romain Linsolas

1
Để kiểm tra xem một phần tử có hiển thị đầy đủ trong một thùng chứa hay không, chỉ cần thêm một tham số bộ chọn bổ sung và sử dụng lại mã elem cho nó. Library.IsElementVisibleInContainer = function (elementSelector, containerSelector) { var containerViewTop = $(containerSelector).offset().top; var containerViewBottom = containerViewTop + $(containerSelector).height();
Cuộc sống



1
Tất cả các câu trả lời sẽ kích hoạt chỉnh lại dòng vì vậy nó có thể là cổ chai, bạn hét lên sử dụng IntersectionObserver nếu được hỗ trợ. Nó sẽ có hiệu suất tốt hơn trên các trình duyệt hiện đại,
jcubic

Câu trả lời:


1258

Cái này cần phải dùng mẹo:

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

Chức năng tiện ích đơn giản Điều này sẽ cho phép bạn gọi một chức năng tiện ích chấp nhận phần tử bạn đang tìm kiếm và nếu bạn muốn phần tử được hiển thị đầy đủ hoặc một phần.

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

Sử dụng

var isElementInView = Utils.isElementInView($('#flyout-left-container'), false);

if (isElementInView) {
    console.log('in view');
} else {
    console.log('out of view');
}

52
Lưu ý rằng điều này chỉ hoạt động nếu tài liệu là phần tử đang được cuộn, tức là bạn không kiểm tra mức độ hiển thị của một số phần tử bên trong ngăn bên trong cuộn.
Andrew B.

8
Làm thế nào để thêm một chút bù đắp?
Jürgen Paul

5
Chỉ hoạt động khi tôi sử dụng window.innerHeightthay thế
Christian Schnorr

2
Cho elemToptôi sử dụng $(elem).position().topvà cho elemBottomtôi sử dụng elemTop + $(elem).outerHeight(true).
Sarah Vessels

13
Mục đích: "Bất kỳ một phần của nguyên tố này theo quan điểm", tôi đã sử dụng: (((elemTop> = docViewTop) && (elemTop <= docViewBottom)) || ((elemBottom> = docViewTop) && (elemBottom <= docViewBottom)))
Grizly

415

Câu trả lời này trong Vanilla:

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

27
cái này không nên isVisible = elementTop < window.innerHeight && elementBottom >= 0sao? Nếu không, một nửa phần tử trên màn hình trả về false.
gman 23/2/2015

7
Không. tôi kiểm tra nếu một số yếu tố được hiển thị đầy đủ trên trang. nếu bạn muốn kiểm tra mức độ hiển thị của một số phần - bạn có thể tùy chỉnh đoạn mã này.
bravedick 24/2/2015

15
Tôi thấy câu trả lời này để thực hiện tốt hơn câu trả lời đã chọn. Đơn giản hơn.
Adam Venezuela

12
So với câu trả lời được phê duyệt, điều này thực hiện waaaay tốt hơn nhiều với hàng trăm yếu tố.
ncla

5
xem một câu đố nhỏ thể hiện ở đây - jsfiddle.net/shaaraddalvi/4rp09jL0
upInCloud

122

Cập nhật: sử dụng IntersectionObserver


Phương pháp tốt nhất tôi tìm thấy cho đến nay là plugin xuất hiện jQuery . Hoạt động như một lá bùa.

Bắt chước một sự kiện "xuất hiện" tùy chỉnh, kích hoạt khi một phần tử cuộn vào chế độ xem hoặc hiển thị cho người dùng.

$('#foo').appear(function() {
  $(this).text('Hello world');
});

Plugin này có thể được sử dụng để ngăn chặn các yêu cầu không cần thiết cho nội dung bị ẩn hoặc bên ngoài khu vực có thể xem được.


30
Đây là một plugin tuyệt vời, không nghi ngờ gì, nhưng không trả lời câu hỏi.
Jon Adams

5
Mặc dù plugin xuất hiện jQuery tốt cho nội dung trên khu vực trang chính, nhưng không may nó có vấn đề với các div cuộn có kích thước cố định với tràn. Sự kiện có thể kích hoạt sớm khi phần tử bị ràng buộc nằm trong vùng có thể xem của trang nhưng bên ngoài vùng có thể xem của div và sau đó không kích hoạt như mong đợi khi phần tử xuất hiện trong div.
Peter

17
Có một plugin biến mất?
Shamoon

3
@Shamoon kiểm tra nguồn cho appear pluginvà có lẽ bạn sẽ chỉ cần thêm một !nơi nào đó để có được một disappearplugin.
Lucky Soni

5
Là một lưu ý, điều này không làm việc với jQuery 1.11.X github.com/morr/jquery.appear/issues/37
Jason Parham

86

Đây là giải pháp JavaScript thuần túy của tôi hoạt động nếu nó cũng được ẩn trong một thùng chứa có thể cuộn được.

Demo tại đây (thử thay đổi kích thước cửa sổ)

var visibleY = function(el){
  var rect = el.getBoundingClientRect(), top = rect.top, height = rect.height, 
    el = el.parentNode
  // Check if bottom of the element is off the page
  if (rect.bottom < 0) return false
  // Check its within the document viewport
  if (top > document.documentElement.clientHeight) return false
  do {
    rect = el.getBoundingClientRect()
    if (top <= rect.bottom === false) return false
    // Check if the element is out of view due to a container scrolling
    if ((top + height) <= rect.top) return false
    el = el.parentNode
  } while (el != document.body)
  return true
};

EDIT 2016-03-26: Tôi đã cập nhật giải pháp cho tài khoản để cuộn qua phần tử để nó được ẩn phía trên đỉnh của hộp chứa có thể cuộn. EDIT 2018-10-08: Được cập nhật để xử lý khi cuộn ra khỏi chế độ xem phía trên màn hình.


cảm ơn, có lẽ tốt hơn return top <= document.documentElement.clientHeight && top >= 0;
Yousef Salimpour

16
+1 Đây là câu trả lời được mã hóa duy nhất (không phải bên thứ ba) có tính đến tính đệ quy của các phần tử. Tôi đã mở rộng để xử lý cuộn ngang, dọc và cuộn trang: jsfiddle.net/9nuqpgqa
Pebbl

3
Giải pháp này chỉ kiểm tra đầu của phần tử. Nếu pixel trên cùng đầu tiên hiển thị, nó sẽ trả về đúng ngay cả khi phần còn lại của mục không hiển thị. Để kiểm tra xem toàn bộ phần tử có thể nhìn thấy hay không, bạn cũng cần kiểm tra thuộc tính dưới cùng.
Wojciech Jakubas 7/2/2016

2
Vâng, gọn gàng! Được sử dụng để giúp viết câu trả lời này (với tín dụng như bình luận của js).
Roamer-1888

Còn thiếu ; sau lần "trả về sai" thứ hai trong vòng lặp
Mikhail Ramendik

46

Sử dụng API IntersectionObserver (tự nhiên trong các trình duyệt hiện đại)

Thật dễ dàng và hiệu quả để xác định xem một phần tử có thể nhìn thấy trong khung nhìn hay trong bất kỳ vùng chứa có thể cuộn nào hay không, bằng cách sử dụng trình quan sát .

Yêu cầu đính kèm một scrollsự kiện và kiểm tra thủ công trên cuộc gọi lại sự kiện đã được loại bỏ, do đó hiệu quả:

// this is the target which is observed
var target = document.querySelector('div');

// configure the intersection observer instance
var intersectionObserverOptions = {
  root: null,
  rootMargin: '150px',
  threshold: 1.0
}
    
var observer = new IntersectionObserver(onIntersection, intersectionObserverOptions);

// provide the observer with a target
observer.observe(target);

function onIntersection(entries){
  entries.forEach(entry => {
    console.clear();
    console.log(entry.intersectionRatio)
    target.classList.toggle('visible', entry.intersectionRatio > 0);
    
    // Are we in viewport?
    if (entry.intersectionRatio > 0) {
      // Stop watching 
      // observer.unobserve(entry.target);
    }
  });
}
.box{ width:100px; height:100px; background:red; margin:1000px; }
.box.visible{ background:green; }
Scroll both Vertically & Horizontally...
<div class='box'></div>


Xem bảng hỗ trợ trình duyệt (không được hỗ trợ trong IE / Safari)


4
Cảm ơn! Điều này hoạt động với tôi và cũng khiến nó hoạt động trong IE11 với github.com/w3c/IntersectionObserver
Matt Wilson

Cho đến nay các giải pháp tốt nhất. Đã làm việc trong IE11 mà không cần polyfill!
Fabian von Ellerts

Lưu ý rằng VẪN này không được hỗ trợ trong iOS / macOS Safari, thật không may. Đảm bảo kiểm tra các sự cố hoàn hảo nếu bạn chọn polyfill, đó là một nhóm lớn người dùng
Leland

@Leland - nó phụ thuộc vào dự án. Đối với tất cả các dự án của tôi, đây là nhóm 0 người dùng tuyệt đối. Tôi không xây dựng trang web nhưng hệ thống web;)
vsync

tôi đang cố chạy cái này trong một vòng lặp trên một số phần tử, nhưng nó không hoạt động. Có ý kiến ​​gì không? Tôi đang thêm phần tử để nhắm mục tiêu trong vòng lặp đó.
Sascha Grindau

42

Plugin jQuery Waypoint rất hay ở đây.

$('.entry').waypoint(function() {
   alert('You have scrolled to an entry.');
});

Có một số ví dụ trên trang web của plugin .


3
Đối với tôi nó chỉ hoạt động với phần bù $('#my-div').waypoint(function() { console.log('Hello there!'); }, { offset: '100%' });
leymannx

21

Làm thế nào về

function isInView(elem){
   return $(elem).offset().top - $(window).scrollTop() < $(elem).height() ;
}

Sau đó, bạn có thể kích hoạt bất cứ điều gì bạn muốn một khi phần tử được xem như thế này

$(window).scroll(function(){
   if (isInView($('.classOfDivToCheck')))
      //fire whatever you what 
      dothis();
})

Điều đó làm việc cho tôi tốt


1
Điều này hoạt động với tôi, nhưng tôi đã sử dụng chức năng, dường như hoàn thiện hơn, isScrolledIntoView tại stackoverflow.com/questions/487073/, :)
Meetai.com

3
Tôi nghĩ rằng nó phải là $ (window) .scrollTop () <$ (elem) .offset (). Top + $ (elem) .height ();
Trẻ

Sửa đổi của tôi sẽ như thế này: `return $ (window) .scrollTop () + $ (window) .height ()> $ (elem) .offset (). Top + $ (elem) .height (); `
bubencode

15

WebResourceDepot đã viết một tập lệnh để tải trong khi cuộn sử dụng jQuery một thời gian trước đây. Bạn có thể xem Live Demo của họ ở đây . Thịt bò của chức năng của họ là thế này:

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

15

Chức năng tuyệt vời của Tweeked Scott Dowding cho yêu cầu của tôi - điều này được sử dụng để tìm kiếm nếu phần tử vừa được cuộn vào màn hình, tức là cạnh trên của nó.

function isScrolledIntoView(elem)
{
    var docViewTop = $(window).scrollTop();
    var docViewBottom = docViewTop + $(window).height();
    var elemTop = $(elem).offset().top;
    return ((elemTop <= docViewBottom) && (elemTop >= docViewTop));
}

12

Vanilla đơn giản để kiểm tra xem phần tử ( el) có thể nhìn thấy trong div ( holder)

function isElementVisible (el, holder) {
  holder = holder || document.body
  const { top, bottom, height } = el.getBoundingClientRect()
  const holderRect = holder.getBoundingClientRect()

  return top <= holderRect.top
    ? holderRect.top - top <= height
    : bottom - holderRect.bottom <= height
},

Sử dụng với jQuery:

var el = $('tr:last').get(0);
var holder = $('table').get(0);
isVisible =  isScrolledIntoView(el, holder);

2
Trong kỷ nguyên Ứng dụng Trang đơn này, việc kiểm tra xem một phần tử có thể nhìn thấy bên trong một số phần tử khác ngoài cửa sổ hay không . Đó là lý do tại sao cái này nhận được upvote của tôi.
H Dog

8

isScrolledIntoView là một hàm rất cần thiết, vì vậy tôi đã thử nó, nó hoạt động cho các phần tử không cao hơn khung nhìn, nhưng nếu phần tử lớn hơn khi khung nhìn thì nó không hoạt động. Để khắc phục điều này dễ dàng thay đổi điều kiện

return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));

đến đây:

return (docViewBottom >= elemTop && docViewTop <= elemBottom);

Xem bản demo tại đây: http://jsfiddle.net/RRSmQ/


8

Hầu hết các câu trả lời ở đây không tính đến việc một yếu tố cũng có thể bị ẩn bởi vì nó được cuộn ra khỏi tầm nhìn của một div, không chỉ của toàn bộ trang.

Để giải quyết khả năng đó, về cơ bản, bạn phải kiểm tra xem phần tử có được định vị bên trong giới hạn của mỗi cha mẹ của nó không.

Giải pháp này thực hiện chính xác điều đó:

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

Nó cũng cho phép bạn chỉ định tỷ lệ phần trăm phải hiển thị theo từng hướng.
Nó không bao gồm khả năng nó có thể bị ẩn do các yếu tố khác, như display: hidden.

Điều này sẽ hoạt động trong tất cả các trình duyệt chính, vì nó chỉ sử dụng getBoundingClientRect. Cá nhân tôi đã thử nghiệm nó trong Chrome và Internet Explorer 11.


Cảm ơn bạn cho mã này. Tôi tự hỏi làm thế nào bạn sẽ thêm trình nghe sự kiện vào cuộn trong trường hợp này rằng bạn có nhiều yếu tố cuộn được lồng nhau? Có vẻ như chỉ thêm người nghe vào cửa sổ thôi là chưa đủ, chúng ta có phải quay trở lại cha mẹ hàng đầu để thêm người nghe vào mỗi thùng chứa có thể cuộn không?
mr1031011

@ mr1031011 Có thể thêm trình xử lý vào cửa sổ và sau đó kiểm tra mục tiêu để xác định vùng chứa đã được cuộn.
Domysee

đúng, nó không hoạt động với ví dụ được đưa ra bởi @vanowm,
mr1031011

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

7

Đây là một giải pháp khác từ http://web-profile.com.ua/

<script type="text/javascript">
$.fn.is_on_screen = function(){
    var win = $(window);
    var viewport = {
        top : win.scrollTop(),
        left : win.scrollLeft()
    };
    viewport.right = viewport.left + win.width();
    viewport.bottom = viewport.top + win.height();

    var bounds = this.offset();
    bounds.right = bounds.left + this.outerWidth();
    bounds.bottom = bounds.top + this.outerHeight();

    return (!(viewport.right < bounds.left || viewport.left > bounds.right ||    viewport.bottom < bounds.top || viewport.top > bounds.bottom));
 };

if( $('.target').length > 0 ) { // if target element exists in DOM
    if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
        $('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info       
    } else {
        $('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
    }
}
$(window).scroll(function(){ // bind window scroll event
if( $('.target').length > 0 ) { // if target element exists in DOM
    if( $('.target').is_on_screen() ) { // if target element is visible on screen after DOM loaded
        $('.log').html('<div class="alert alert-success">target element is visible on screen</div>'); // log info
    } else {
        $('.log').html('<div class="alert">target element is not visible on screen</div>'); // log info
    }
}
});
</script>

Xem nó trong JSFiddle


7

Điều này xem xét bất kỳ phần đệm, đường viền hoặc lề mà phần tử có cũng như các phần tử lớn hơn chính khung nhìn.

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

Để gọi nó sử dụng một cái gì đó như thế này:

var $myElement = $('#my-element'),
    canUserSeeIt = inViewport($myElement);

console.log(canUserSeeIt); // true, if element is visible; false otherwise

7

Có một plugin cho jQuery được gọi là inview có thêm một sự kiện "inview" mới.


Đây là một số mã cho một plugin jQuery không sử dụng các sự kiện:

$.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 );

Tôi đã tìm thấy điều này trong một bình luận ở đây ( http://remysharp.com/2009/01/26/element-in-view-event-plugin/ ) bởi một người tên là James


Than ôi, jQuery inview không còn được duy trì và không hoạt động với các phiên bản hiện tại của jQuery.
mikemaccana

1
JQuery 1 là để hỗ trợ trình duyệt cũ, các tính năng mới có trong jQuery 2.
mikemaccana 17/12/14

Liên kết không hiển thị ví dụ như trang đã được cập nhật.
Giáo sư lập trình

6

Tôi cần kiểm tra khả năng hiển thị trong các phần tử bên trong container DIV có thể cuộn

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

cái này hoạt động với tôi nếu tôi thay đổi e.style.opacity > 0thành (!e.style.opacity || e.style.opacity > 0)bởi vì theo mặc định nó là chuỗi trống cho tôi trong FF.
Brett Zamir

6

Dựa trên câu trả lời tuyệt vời này , bạn có thể đơn giản hóa nó hơn một chút bằng ES2015 +:

function isScrolledIntoView(el) {
  const { top, bottom } = el.getBoundingClientRect()
  return top >= 0 && bottom <= window.innerHeight
}

Nếu bạn không quan tâm đến phần trên cùng của cửa sổ và chỉ quan tâm rằng phần dưới đã được xem, điều này có thể được đơn giản hóa để

function isSeen(el) {
  return el.getBoundingClientRect().bottom <= window.innerHeight
}

hoặc thậm chí một lớp lót

const isSeen = el => el.getBoundingClientRect().bottom <= window.innerHeight

4

Bạn có thể sử dụng plugin jquery "onScreen" để kiểm tra xem phần tử có trong chế độ xem hiện tại khi bạn cuộn không. Plugin đặt ": onScreen" của bộ chọn thành true khi bộ chọn xuất hiện trên màn hình. Đây là liên kết cho plugin mà bạn có thể đưa vào dự án của mình. " http://benpickles.github.io/onScreen/jquery.onscreen.min.js "

Bạn có thể thử ví dụ dưới đây phù hợp với tôi.

$(document).scroll(function() {
    if($("#div2").is(':onScreen')) {
        console.log("Element appeared on Screen");
        //do all your stuffs here when element is visible.
    }
    else {
        console.log("Element not on Screen");
        //do all your stuffs here when element is not visible.
    }
});

Mã HTML:

<div id="div1" style="width: 400px; height: 1000px; padding-top: 20px; position: relative; top: 45px"></div> <br>
<hr /> <br>
<div id="div2" style="width: 400px; height: 200px"></div>

CSS:

#div1 {
    background-color: red;
}
#div2 {
    background-color: green;
}

3

Tôi có một phương thức như vậy trong ứng dụng của mình, nhưng nó không sử dụng 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));
}

Chỉnh sửa: Phương pháp này hoạt động tốt cho IE (ít nhất là phiên bản 6). Đọc các bình luận để tương thích với FF.


2
Vì một số lý do document.body.scrollTop luôn trả về 0 (trên ff3). Thay đổi nó thành var thấyTop = (document.documentEuity.scrollTop? Document.documentEuity.scrollTop: document.body.scrollTop);
yoavf

Xin lỗi vì điều đó. Ứng dụng của tôi chỉ phải chạy trong IE 6 (vâng, tôi không may mắn :(), vì vậy tôi chưa bao giờ thử nghiệm điều này trong FF ...
Romain Linsolas

Đây sẽ là câu trả lời tốt nhất ở đây nếu nó đúng. Sửa một trong những dòng của bạn về điều này: var visibleBottom = visibleTop + window.innerHeight;Tôi không sử dụng jQuery và bạn đã giúp tôi tìm câu trả lời đúng.
Bitterblue

3

Nếu bạn muốn điều chỉnh mục này để cuộn mục trong div khác,

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

3

Sửa đổi câu trả lời được chấp nhận để phần tử phải đặt thuộc tính hiển thị của nó thành một cái gì đó khác với "không" thành chất lượng như có thể nhìn thấy.

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

3

Đây là một cách để đạt được điều tương tự bằng Mootools, theo chiều ngang, dọc hoặc cả hai.

Element.implement({
inVerticalView: function (full) {
    if (typeOf(full) === "null") {
        full = true;
    }

    if (this.getStyle('display') === 'none') {
        return false;
    }

    // Window Size and Scroll
    var windowScroll = window.getScroll();
    var windowSize = window.getSize();
    // Element Size and Scroll
    var elementPosition = this.getPosition();
    var elementSize = this.getSize();

    // Calculation Variables
    var docViewTop = windowScroll.y;
    var docViewBottom = docViewTop + windowSize.y;
    var elemTop = elementPosition.y;
    var elemBottom = elemTop + elementSize.y;

    if (full) {
        return ((elemBottom >= docViewTop) && (elemTop <= docViewBottom)
            && (elemBottom <= docViewBottom) && (elemTop >= docViewTop) );
    } else {
        return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
    }
},
inHorizontalView: function(full) {
    if (typeOf(full) === "null") {
        full = true;
    }

    if (this.getStyle('display') === 'none') {
        return false;
    }

    // Window Size and Scroll
    var windowScroll = window.getScroll();
    var windowSize = window.getSize();
    // Element Size and Scroll
    var elementPosition = this.getPosition();
    var elementSize = this.getSize();

    // Calculation Variables
    var docViewLeft = windowScroll.x;
    var docViewRight = docViewLeft + windowSize.x;
    var elemLeft = elementPosition.x;
    var elemRight = elemLeft + elementSize.x;

    if (full) {
        return ((elemRight >= docViewLeft) && (elemLeft <= docViewRight)
            && (elemRight <= docViewRight) && (elemLeft >= docViewLeft) );
    } else {
        return ((elemRight <= docViewRight) && (elemLeft >= docViewLeft));
    }
},
inView: function(full) {
    return this.inHorizontalView(full) && this.inVerticalView(full);
}});

3

Một ví dụ dựa trên câu trả lời này để kiểm tra xem một phần tử có thể nhìn thấy 75% hay không (tức là dưới 25% trong số đó là ngoài màn hình).

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

3

Có hơn 30 câu trả lời cho câu hỏi này và không ai trong số họ sử dụng giải pháp JS đơn giản, tuyệt vời mà tôi đang sử dụng. Không cần phải tải jQuery chỉ để giải quyết vấn đề này, vì nhiều người khác đang thúc đẩy.

Để cho biết phần tử có nằm trong khung nhìn hay không, trước tiên chúng ta phải xác định vị trí phần tử trong phần thân. Chúng ta không cần phải làm điều này một cách đệ quy như tôi từng nghĩ. Thay vào đó, chúng ta có thể sử dụng element.getBoundingClientRect().

pos = elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top;

Giá trị này là chênh lệch Y giữa đỉnh của vật và đỉnh của thân.

Sau đó chúng ta phải cho biết nếu phần tử nằm trong tầm nhìn. Hầu hết các triển khai đều hỏi liệu phần tử đầy đủ có nằm trong khung nhìn hay không, vì vậy đây là những gì chúng ta sẽ đề cập.

Trước hết, vị trí trên cùng của cửa sổ là: window.scrollY .

Chúng ta có thể có được vị trí dưới cùng của cửa sổ bằng cách thêm chiều cao của cửa sổ vào vị trí trên cùng của nó:

var window_bottom_position = window.scrollY + window.innerHeight;

Cho phép tạo một chức năng đơn giản để có được vị trí hàng đầu của phần tử:

function getElementWindowTop(elem){
    return elem && typeof elem.getBoundingClientRect === 'function' ? elem.getBoundingClientRect().top - document.body.getBoundingClientRect().top : 0;
}

Hàm này sẽ trả về vị trí trên cùng của phần tử trong cửa sổ hoặc nó sẽ trả về 0nếu bạn chuyển cho nó một cái gì đó không phải là phần tử có.getBoundingClientRect() phương thức. Phương pháp này đã có từ lâu, vì vậy bạn không cần phải lo lắng về việc trình duyệt của mình không hỗ trợ.

Bây giờ, vị trí hàng đầu của yếu tố của chúng tôi là:

var element_top_position = getElementWindowTop(element);

Và vị trí dưới cùng của phần tử là:

var element_bottom_position = element_top_position + element.clientHeight;

Bây giờ chúng ta có thể xác định xem phần tử có nằm trong chế độ xem hay không bằng cách kiểm tra xem vị trí dưới cùng của phần tử có thấp hơn vị trí trên cùng của chế độ xem hay không và bằng cách kiểm tra xem vị trí trên cùng của phần tử có cao hơn vị trí dưới cùng của chế độ xem không:

if(element_bottom_position >= window.scrollY 
&& element_top_position <= window_bottom_position){
    //element is in view
else
    //element is not in view

Từ đó, bạn có thể thực hiện logic để thêm hoặc xóa in-view lớp trên phần tử của mình, sau đó bạn có thể xử lý các hiệu ứng chuyển tiếp trong CSS của mình.

Tôi hoàn toàn ngạc nhiên khi tôi không tìm thấy giải pháp này ở bất kỳ nơi nào khác, nhưng tôi tin rằng đây là giải pháp sạch nhất và hiệu quả nhất và nó không yêu cầu bạn phải tải jQuery!


Giải thích rất hay! Nhưng đã có câu trả lời thực hiện chính xác những gì bạn làm, như câu trả lời của Ally
Domysee

1
@Domysee Hmm, bằng cách nào đó tôi đã bỏ qua điều đó. Đủ công bằng. Cảm ơn bạn đã chỉ ra rằng mặc dù. Thật tuyệt khi thấy điều này được thực hiện theo cách khác.
WebWanderer

3

Một phiên bản hiệu quả hơn của câu trả lời này :

 /**
 * Is element within visible region of a scrollable container
 * @param {HTMLElement} el - element to test
 * @returns {boolean} true if within visible region, otherwise false
 */
 function isScrolledIntoView(el) {
      var rect = el.getBoundingClientRect();
      return (rect.top >= 0) && (rect.bottom <= window.innerHeight);
 }

2

Phương pháp này sẽ trả về true nếu bất kỳ phần nào của phần tử hiển thị trên trang. Nó hoạt động tốt hơn trong trường hợp của tôi và có thể giúp đỡ người khác.

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

2

Sửa đổi đơn giản cho div cuộn (container)

var isScrolledIntoView = function(elem, container) {
    var containerHeight = $(container).height();
    var elemTop = $(elem).position().top;
    var elemBottom = elemTop + $(elem).height();
    return (elemBottom > 0 && elemTop < containerHeight);
}

LƯU Ý: điều này không hoạt động nếu phần tử lớn hơn div có thể cuộn.


2

Tôi đã điều chỉnh phần mở rộng hàm jQuery ngắn này mà bạn có thể cảm thấy thoải mái khi sử dụng (giấy phép MIT).

/**
 * returns true if an element is visible, with decent performance
 * @param [scope] scope of the render-window instance; default: window
 * @returns {boolean}
 */
jQuery.fn.isOnScreen = function(scope){
    var element = this;
    if(!element){
        return;
    }
    var target = $(element);
    if(target.is(':visible') == false){
        return false;
    }
    scope = $(scope || window);
    var top = scope.scrollTop();
    var bot = top + scope.height();
    var elTop = target.offset().top;
    var elBot = elTop + target.height();

    return ((elBot <= bot) && (elTop >= top));
};

2

Tôi đã viết một thành phần cho tác vụ, được thiết kế để xử lý số lượng lớn các phần tử cực kỳ nhanh (để điều chỉnh <10ms cho 1000 phần tử trên điện thoại di động chậm ).

Nó hoạt động với mọi loại thùng chứa cuộn mà bạn có quyền truy cập - cửa sổ, các phần tử HTML, iframe được nhúng, cửa sổ con được sinh ra - và rất linh hoạt trong những gì nó phát hiện ( khả năng hiển thị toàn bộ hoặc một phần , hộp viền hoặc hộp nội dung , vùng dung sai tùy chỉnh , v.v. ).

Một bộ thử nghiệm khổng lồ, chủ yếu được tạo tự động đảm bảo rằng nó hoạt động như quảng cáo, trình duyệt chéo .

Cung cấp cho nó một shot nếu bạn thích: jQuery.isInView . Mặt khác, bạn có thể tìm thấy cảm hứng trong mã nguồn, ví dụ ở đây .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.