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


当前回答

我找到的最简单的解决方案是交集观察者API:

var observer = new IntersectionObserver(function(entries) {
    if(entries[0].isIntersecting === true)
        console.log('Element has just become visible in screen');
}, { threshold: [0] });

observer.observe(document.querySelector("#main-container"));

其他回答

制作了一个简单的插件,用于检测元素在可滚动容器中是否可见

    $.fn.isVisible = function(){

      var win;
      if(!arguments[0])
      {
        console.error('Specify a target;');
        return false;
      }
      else
      {
        win = $(arguments[0]);
      }
      var viewport = {};
      var bounds = this.offset();
      bounds.right = bounds.left + this.outerWidth();
      bounds.bottom = bounds.top + this.outerHeight();
      viewport.bottom = win.height() + win.offset().top;
      return (!( bounds.top > viewport.bottom) && (win.offset().top < bounds.bottom));
    };

像这样调用$('elem_to_check').isVisible('scrollable_container');

希望能有所帮助。

我改编了这个简短的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));
};

检查元素是否在屏幕上,而不是公认的检查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);
}

我添加了我的代码修改。不幸的是,我可以看到每个人都在他们的版本,每个人都忽略了debance功能的使用。哪个答案是让你的事件不触发,例如,在滚动时每秒200次。

$(window).scroll(function(){
        if (isInView($('.class'))){
            debounce(
                someFunction(), 5
            )
        }
    });
    function isInView(elem){
        if(document.documentElement.clientWidth > 991){
            return $(elem).offset().top - $(window).scrollTop() < $(elem).height();
        }else {
            doSometing;
        }
    }

这里的大多数答案都没有考虑到一个元素也可以被隐藏,因为它被滚动出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上测试了它。