2013-04-30 7 views
8

次の問題に対する適切な解決策を見つける必要があります。私は、要素がページまたはブラウザウィンドウのためのビューのポートにあるかどうかを追跡することを頼んでいる多くの人々を見る。私はこのアクションを複製することができる必要がありますが、スクロールするDIVの内部では、オーバーフロー:スクロールなどの方法が必要です。誰かがこの具体的な行動の良い例を知っていますか?スクロール可能なdiv内の要素が表示されていないときを検出します

ありがとうございます。

答えて

18

私は前に同じ問題があった、私は次のfunction.the最初のパラメータは、チェックする要素のために終わった、2番目は、要素が部分的に面白いかどうかを確認することです。水平スクロールを確認するためにそれを拡張することができます。

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

+0

それを聞いてうれしい、私はそれのための簡単なjqueryのプラグインを作成します:) –

+0

私は同じことをやっていた。 l – Ronny

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関数でoffsetTopを追加する必要があります。 '' 'let cTop = container.scrollTop + container.offsetTop''' –

+0

それは私にとってはうまくいかないようです。 –

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

ベストアンサーに基づく。要素が部分的に表示されているかどうかを伝えるのではなく、私は少し余分を追加したので、要素がx%以上可視かどうかを示すパーセンテージ(0-100)を渡すことができます。

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

+1

はいjQueryを避けたい –

関連する問題