2013-04-30 73 views
8

我需要爲以下問題找到一個很好的解決方案。我看到很多人詢問跟蹤頁面或瀏覽器窗口中的元素是否位於視圖端口之內或之外。我需要能夠複製這個動作,但是在一個滾動的DIV中,溢出:例如滾動。有沒有人知道這個具體行動的一個很好的例子?檢測滾動div內的元素何時不在視圖中

在此先感謝。

回答

18

我以前有同樣的問題,我已經結束了以下功能。第一個參數是要檢查的元素,第二個是檢查元素是否部分inview.it僅用於垂直檢查,你可以擴展它來檢查水平滾動。

function checkInView(elem,partial) 
{ 
    var container = $(".scrollable"); 
    var contHeight = container.height(); 
    var contTop = container.scrollTop(); 
    var contBottom = contTop + contHeight ; 

    var elemTop = $(elem).offset().top - container.offset().top; 
    var elemBottom = elemTop + $(elem).height(); 

    var isTotal = (elemTop >= 0 && elemBottom <=contHeight); 
    var isPart = ((elemTop < 0 && elemBottom > 0) || (elemTop > 0 && elemTop <= container.height())) && partial ; 

    return isTotal || isPart ; 
} 

檢查它在jsFiddle

+1

謝謝。我看到了不同的解決方案,這是完成它的最清晰,最乾淨的方法。謝謝! – Ronny 2013-05-01 23:19:49

+0

很高興聽到這一點,我會做一個簡單的jQuery插件:) – 2013-05-02 09:52:21

+0

我只是做同樣的事情。大聲笑 – Ronny 2013-05-03 02:03:39

0

我做了一個jQuery插件與最近的答案:

(function($) { 
    $.fn.reallyVisible = function(opt) { 

     var options = $.extend({ 
      cssChanges:[ 
       { name : 'visibility', states : ['hidden','visible'] } 
      ], 
      childrenClass:'mentioners2', 
      partialview : true 
     }, opt); 

     var container = $(this); 
     var contHeight; 
     var contTop; 
     var contBottom; 
     var _this = this; 
     var _children; 

     this.checkInView = function(elem,partial){ 

      var elemTop = $(elem).offset().top - container.offset().top; 
      var elemBottom = elemTop + $(elem).height(); 

      var isTotal = (elemTop >= 0 && elemBottom <=contHeight); 
      var isPart = ((elemTop < 0 && elemBottom > 0) || (elemTop > 0 && elemTop <= container.height())) && partial ; 

      return isTotal || isPart ; 
     } 

     this.bind('restoreProperties',function(){ 
      $.each(_children,function(i,elem){ 
       $.each(options.cssChanges,function(i,_property){ 
        $(elem).css(_property.name,_property.states[1]);   
       }); 
      }); 
      _children = null; 
     }); 

     return this.each(function(){ 
      contHeight = container.height(); 
      contTop = container.scrollTop(); 
      contBottom = contTop + contHeight ; 

      _children = container.children("."+options.childrenClass); 

      $.each(_children,function(i,elem){ 
       var res = _this.checkInView(elem,options.partialview); 
       if( !res){ 
        $.each(options.cssChanges,function(i,_property){ 
         $(elem).css(_property.name,_property.states[0]);   
        }); 
       } 
      }); 

     }); 
    } 

})(jQuery); 
4

這裏是公認的答案的純JavaScript版本,而不依賴於jQuery和一些修復的部分,鑑於檢測和支持拿出來看在上面。

function checkInView(container, element, partial) { 

    //Get container properties 
    let cTop = container.scrollTop; 
    let cBottom = cTop + container.clientHeight; 

    //Get element properties 
    let eTop = element.offsetTop; 
    let eBottom = eTop + element.clientHeight; 

    //Check if in view  
    let isTotal = (eTop >= cTop && eBottom <= cBottom); 
    let isPartial = partial && (
     (eTop < cTop && eBottom > cTop) || 
     (eBottom > cBottom && eTop < cBottom) 
    ); 

    //Return outcome 
    return (isTotal || isPartial); 
} 

作爲獎勵,該功能確保元件是鑑於如果它不是(部分或全部):

function ensureInView(container, element) { 

    //Determine container top and bottom 
    let cTop = container.scrollTop; 
    let cBottom = cTop + container.clientHeight; 

    //Determine element top and bottom 
    let eTop = element.offsetTop; 
    let eBottom = eTop + element.clientHeight; 

    //Check if out of view 
    if (eTop < cTop) { 
     container.scrollTop -= (cTop - eTop); 
    } 
    else if (eBottom > cBottom) { 
     container.scrollTop += (eBottom - cBottom); 
    } 
} 
+0

在你的ensureInView函數應該添加偏移頂部 '''讓cTop = container.scrollTop + container.offsetTop''' – 2017-03-27 20:22:26

+0

這似乎不適用於我,它實際上打破了我的用例中的功能。 – 2017-03-28 23:07:56

0

這裏是一個純JavaScript溶液。

function elementIsVisible(element, container, partial) { 
    var contHeight = container.offsetHeight, 
    elemTop = offset(element).top - offset(container).top, 
    elemBottom = elemTop + element.offsetHeight; 
    return (elemTop >= 0 && elemBottom <= contHeight) || 
    (partial && ((elemTop < 0 && elemBottom > 0) || (elemTop > 0 && elemTop <= contHeight))) 
} 

// checks window 
function isWindow(obj) { 
    return obj != null && obj === obj.window; 
} 

// returns corresponding window 
function getWindow(elem) { 
    return isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView; 
} 

// taken from jquery 
// @returns {{top: number, left: number}} 
function offset(elem) { 

    var docElem, win, 
     box = { top: 0, left: 0 }, 
     doc = elem && elem.ownerDocument; 

    docElem = doc.documentElement; 

    if (typeof elem.getBoundingClientRect !== typeof undefined) { 
     box = elem.getBoundingClientRect(); 
    } 
    win = getWindow(doc); 
    return { 
     top: box.top + win.pageYOffset - docElem.clientTop, 
     left: box.left + win.pageXOffset - docElem.clientLeft 
    }; 
}; 
1

根據最佳答案。而不是僅僅告訴你一個元素是否部分可見。我添加了一些額外的東西,所以你可以傳入一個百分比(0-100),告訴你該元素是否超過x%可見。

function (container, element, partial) { 
    var cTop = container.scrollTop; 
    var cBottom = cTop + container.clientHeight; 
    var eTop = element.offsetTop; 
    var eBottom = eTop + element.clientHeight; 
    var isTotal = (eTop >= cTop && eBottom <= cBottom); 
    var isPartial; 

    if (partial === true) { 
     isPartial = (eTop < cTop && eBottom > cTop) || (eBottom > cBottom && eTop < cBottom); 
    } else if(typeof partial === "number"){ 
     if (eTop < cTop && eBottom > cTop) { 
      isPartial = ((eBottom - cTop) * 100)/element.clientHeight > partial; 
     } else if (eBottom > cBottom && eTop < cBottom){ 
      isPartial = ((cBottom - eTop) * 100)/element.clientHeight > partial; 
     } 
    } 
    return (isTotal || isPartial); 
} 
+0

這也是jQuery免費的。 – Rolf 2017-08-30 10:48:59

+1

是的,我喜歡避免jQuery – 2017-09-08 10:11:40

相關問題