代码之家  ›  专栏  ›  技术社区  ›  Cray

当内容位于可见视区时启动jquery动画

  •  0
  • Cray  · 技术社区  · 5 年前

    我正在通过ajax加载元素。其中一些只有向下滚动页面时才可见。
    有没有办法让我知道一个元素现在是否在页面的可见部分?

    0 回复  |  直到 6 年前
        1
  •  1194
  •   Andrea Casaccia    8 年前

    这应该可以做到:

    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');
    }
    
        2
  •  348
  •   jcubic    7 年前

    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;
    }
    
        3
  •  118
  •   Aoi Karasu    11 年前

    到目前为止,我发现最好的方法是 jQuery appear plugin . 很有魅力。

    模拟一个自定义的“出现”事件,当元素滚动到视图中或以其他方式对用户可见时触发。

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

    此插件可用于防止对隐藏或不在可视区域内的内容的不必要请求。

        4
  •  76
  •   Ally    6 年前

    这是我的纯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:我已经更新了解决方案,以说明滚动过元素,因此它隐藏在可滚动容器顶部上方。 编辑2018-10-08:在屏幕上方滚动出视图时更新为处理。

        5
  •  41
  •   Fedir RYKHTIK    13 年前

    jquery航路点插件在这里非常好。

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

    有一些关于 site of the plugin .

        6
  •  19
  •   sectus    9 年前

    怎么样

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

    在那之后,一旦元素像这样出现在视图中,你就可以触发你想要的任何东西

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

    对我来说很好

        7
  •  16
  •   vsync Qantas 94 Heavy    6 年前

    使用(“new”) IntersectionObserver 美国石油学会

    确定元素是否在视口中可见是非常容易和有效的。通过使用 观察者 ,它不需要附加 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>

    View browsers support table (IE/Safari不支持)

        8
  •  14
  •   Sampson    16 年前

    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();
        });
    };
    
        9
  •  13
  •   Snigdha Batra    11 年前

    tweeked scott dowding的酷函数满足我的需求- 这用于查找元素是否刚刚滚动到屏幕上,即它的上边缘。

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

    这里的大多数答案都没有考虑到元素也可以隐藏,因为它是从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中亲自测试过。

        11
  •  7
  •   Robert    11 年前

    牛角豆视图 是一个非常需要的函数,所以我尝试了它,它对比视窗高的元素有效,但是如果元素比视窗大,它就不起作用。为了解决这个问题很容易改变状况

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

    对此:

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

    请参见此处的演示: http://jsfiddle.net/RRSmQ/

        12
  •  6
  •   Pascal Gagneur    15 年前
    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));
    }
    
        13
  •  6
  •   Brent Barbata    10 年前

    这将考虑元素所具有的任何填充、边框或边距以及大于视口本身的元素。

    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
    
        14
  •  6
  •   ness-EE    6 年前

    有一个 plugin for jQuery called 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/ )一个叫詹姆斯的家伙

        15
  •  5
  •   Adrian P.    10 年前

    这是另一个解决方案 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

        16
  •  5
  •   Brett Zamir    10 年前

    我需要检查可滚动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);
        }
    
        17
  •  5
  •   Pedro Bernardo Denis Matafonov    6 年前

    纯香草味,检查元素是否( 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);
    
        18
  •  4
  •   Vasuki Dileep    9 年前

    您可以使用jquery插件“onscreen”在滚动时检查元素是否在当前视图中。 当选择器出现在屏幕上时,插件将选择器的“:on screen”设置为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;
    }
    
        19
  •  4
  •   Community TTT    7 年前

    建造 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
    
        20
  •  3
  •   Romain Linsolas    16 年前

    我的应用程序中有这样一个方法,但它不使用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的兼容性。

        21
  •  3
  •   Samiya Akhtar    11 年前

    如果你想调整这个在另一个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)); 
    }
    
        22
  •  3
  •   evanmcd    11 年前

    修改了接受的答案,以便元素必须将其display属性设置为“none”以外的值,才能使质量保持可见。

    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);
    }
    
        23
  •  3
  •   bmlkc    10 年前

    这里是一种使用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);
    }});
    
        24
  •  3
  •   Community TTT    7 年前

    一个基于 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;
    }
    
        25
  •  2
  •   Rafael Garcia    10 年前

    如果元素的任何部分在页面上可见,则此方法将返回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;
    }
    
        26
  •  2
  •   Derrick J Wippler    10 年前

    可滚动div(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);
    }
    

    注意:如果元素大于可滚动div,则此操作不起作用。

        27
  •  2
  •   Lorenz Lo Sauer    10 年前

    我修改了这个简短的jquery函数扩展,您可以随意使用(mit license)。

    /**
     * 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));
    };
    
        28
  •  2
  •   hashchange    9 年前

    我已经写了 a component 对于任务,设计用于处理大量元素 extremely fast (1000个元素的10毫秒 在慢速移动设备上 )

    它适用于您可以访问“窗口、html元素、嵌入iframe、派生子窗口”的每种类型的滚动容器,并且在检测到的内容上非常灵活( full or partial visibility , border box or content box 习俗 tolerance zone , etc )

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

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

        29
  •  2
  •   Sonny Lloyd    9 年前

    我正在寻找一种方法来查看元素是否会很快出现在视图中,因此通过扩展上面的片段,我成功地做到了这一点。我想我会把这个留在这里以防万一

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

    scrollement=您可以通过 窗口 或具有滚动条的父元素

    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));
            }
        30
  •  2
  •   Adam Pietrasiak    8 年前

    我更喜欢使用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 事件功能等,每次用户滚动视图时检查。