首页 文章

滚动后检查元素是否可见

提问于
浏览
1006

我正在通过AJAX加载元素 . 只有向下滚动页面时,其中一些才可见 .
有什么方法我可以知道元素现在是否在页面的可见部分?

30 回答

  • 3

    这是我的纯JavaScript解决方案,如果它也隐藏在可滚动容器中,它也可以工作 .

    Demo here(尝试调整窗口大小)

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

    编辑2016-03-26:我've updated the solution to account for scrolling past the element so it'隐藏在可滚动容器的顶部之上 . 编辑2018-10-08:更新以在屏幕上方滚动视图时进行处理 .

  • 2

    我需要检查可滚动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);
        }
    
  • 3

    我更喜欢使用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 事件函数等中轻松添加此类代码,以便每次用户滚动视图时进行检查 .

  • 9

    jQuery Waypoints插件在这里非常好用 .

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

    site of the plugin上有一些例子 .

  • 4

    使用(“new”)IntersectionObserver API

    确定视口中是否有可见元素非常简单有效 . 通过使用观察者,它消除了附加 scroll 事件和手动检查事件回调的需要 .

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

    查看浏览器支持表(IE / Safari不支持)

  • 1153

    WebResourcesDepot写了a script to load while scrolling,前一段时间使用jQuery . 你可以查看他们的Live Demo Here . 他们功能的牛肉是这样的:

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

    基于this answer的示例,用于检查元素是否可见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;
    }
    
  • 5

    这会考虑元素具有的任何填充,边框或边距以及大于视口本身的元素 .

    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
    
  • 6

    Build this great answer,您可以使用ES2015进一步简化它:

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

    如果您不关心顶部窗外,只关心底部已被查看,这可以简化为

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

    甚至是单行班轮

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

    普通香草检查元素( el )是否在可滚动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
    },
    

    用于jQuery:

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

    我已经为这项任务编写了a component,旨在处理大量元素extremely fast(在慢速移动设备上为1000个元素调整<10ms) .

    它适用于您可以访问的每种类型的滚动容器 - 窗口,HTML元素,嵌入式iframe,衍生的子窗口 - 并且在检测到的内容方面非常灵活(full or partial visibilityborder box or content box,custom tolerance zoneetc) .

    一个巨大的,主要是自动生成的测试套件可确保它像宣传的那样工作,cross-browser .

    如果你愿意,可以试一试:jQuery.isInView . 否则,您可能会在源代码中找到灵感,例如: here .

  • 17

    This answer在香草:

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

    这是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>
    

    JSFiddle中看到它

  • 5

    我改编了这个简短的jQuery函数扩展,您可以随意使用(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

    怎么样

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

    之后,一旦元素在视图中,你可以触发你想要的任何东西

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

    这对我很有用

  • 3

    这里的大多数答案没有考虑到元素也可以被隐藏,因为它被滚动到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中测试过它 .

  • 2

    如果你想调整这个在另一个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)); 
    }
    
  • 6

    可滚动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,则此方法无效 .

  • 2

    这是一种使用Mootools在水平,垂直或两者中实现相同功能的方法 .

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

    我的应用程序中有这样的方法,但它不使用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));
    }
    

    编辑:这种方法适用于I.E. (至少版本6) . 阅读注释以了解与FF的兼容性 .

  • 2

    到目前为止我找到的最好的方法是jQuery appear plugin . 奇迹般有效 .

    模仿自定义“出现”事件,当元素滚动到视图中或以其他方式对用户可见时触发 . $('#foo') . 出现(function(){
    $(this).text('Hello world');
    });
    此插件可用于防止对隐藏或可视区域外的内容进行不必要的请求 .

  • 2

    您可以使用jquery插件"onScreen"来滚动时检查元素是否在当前视口中 . 当选择器出现在屏幕上时,插件将选择器的":onScreen"设置为true . 这是插件的链接您可以在项目中包含哪些内容 . “http://benpickles.github.io/onScreen/jquery.onscreen.min.js

    您可以尝试以下适用于我的示例 .

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

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

    我正在寻找一种方法来查看该元素是否即将进入视图,因此通过扩展上面的片段,我设法做到了 . 以为我会留在这里以防万一它会帮助别人

    elm =是您要检查的元素在视图中

    scrollElement =您可以传递 window 或具有滚动的父元素

    offset =如果你希望它在元素在屏幕之前200px之前触发,然后传递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));
            }
    
  • 1
    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));
    }
    
  • 2

    如果元素的任何部分在页面上可见,则此方法将返回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;
    }
    
  • 14

    修改了已接受的答案,以便元素必须将其显示属性设置为“无”以外的其他内容,以使质量可见 .

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

    这应该是诀窍:

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

    Simple Utility Function 这将允许您调用一个实用程序函数,该函数接受您正在查找的元素,以及您希望元素完全在视图中还是部分在视图中 .

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

    Usage

    var isElementInView = Utils.isElementInView($('#flyout-left-container'), false);
    
    if (isElementInView) {
        console.log('in view');
    } else {
        console.log('out of view');
    }
    
  • 2

    isScrolledIntoView 是一个非常需要的函数,所以我尝试了它,它适用于不比视口更高的元素,但如果元素比视口更大则不起作用 . 要解决此问题,请轻松更改条件

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

    对此:

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

    在这里看演示:http://jsfiddle.net/RRSmQ/

  • 67

    根据我的要求推荐了Scott Dowding的酷功能 - 这用于查找元素是否刚刚滚动到屏幕中,即它的顶部边缘 .

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

    有一个plugin for jQuery called inview会添加一个新的"inview"事件 .


    以下是一些不使用事件的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 );
    

    我在一个名叫詹姆斯的家伙的评论中发现了这个(http://remysharp.com/2009/01/26/element-in-view-event-plugin/

相关问题