2013-04-30 9 views
8

Ich muss eine gute Lösung für das folgende Problem finden. Ich sehe eine Menge Leute, die nach Tracking fragen, wenn sich ein Element innerhalb oder außerhalb des View-Ports für die Seite oder das Browser-Fenster befindet. Ich muss in der Lage sein, diese Aktion zu replizieren, aber in einem DIV, das scrollt, mit Überlauf: scroll zum Beispiel. Kennt jemand ein gutes Beispiel für diese spezielle Aktion?Ermitteln, wenn Elemente innerhalb eines scrollbaren div sind nicht sichtbar

Vielen Dank im Voraus.

Antwort

18

Ich hatte das gleiche Problem vor, ich habe mit der folgenden Funktion endete.der erste Parameter ist für das Element zu überprüfen, die zweite ist zu überprüfen, ob das Element teilweise inview.it ist nur für die vertikale Prüfung Sie können es erweitern, um nach horizontaler Bildlauf zu suchen.

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

überprüfen Sie es auf jsFiddle.

+1

Danke. Ich habe verschiedene Lösungen dafür gesehen, und dies ist die klarste und sauberste Methode, dies zu erreichen. Vielen Dank! – Ronny

+0

schön, das zu hören, ich werde ein einfaches jquery-Plugin dafür machen :) –

+0

Ich habe nur das Gleiche gemacht. lol – Ronny

0

Ich habe eine jQuery-Plugin mit der letzten Antwort:

(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

Hier ist eine reine JavaScript-Version der Antwort akzeptiert, ohne auf jQuery zu verlassen und mit einigen Korrekturen auf die teilweise im Hinblick auf Erkennung und Unterstützung für aus der Sicht oben drauf.

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

Und als Bonus, sorgt diese Funktion das Element sichtbar ist, wenn es nicht (teilweise oder vollständig) ist:

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

In Ihrer useInView-Funktion sollte offsetTop '' 'hinzufügen cTop = container.scrollTop + container.offsetTop''' –

+0

Das scheint nicht für mich arbeiten, es bricht tatsächlich die Funktion in meinem Anwendungsfall. –

0

ist hier eine reine Javascript-Lösung.

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

Basierend auf der besten Antwort. Anstatt nur zu sagen, ob ein Element teilweise sichtbar ist oder nicht. Ich habe ein kleines Extra hinzugefügt, so dass Sie einen Prozentsatz (0-100) eingeben können, der Ihnen sagt, ob das Element mehr als x% sichtbar ist.

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

Dies ist auch jQuery-frei. – Rolf

+1

Ja, ich möchte jQuery vermeiden –