So überprüfen Sie, ob ein Element außerhalb des Bildschirms liegt

81

Ich muss mit jQuery prüfen, ob ein DIV-Element nicht vom Bildschirm fällt. Die Elemente sind sichtbar und werden gemäß den CSS-Attributen angezeigt. Sie können jedoch absichtlich außerhalb des Bildschirms platziert werden durch:

position: absolute; 
left: -1000px; 
top: -1000px;

Ich konnte den jQuery- :visibleSelektor nicht verwenden, da das Element eine Höhe und Breite ungleich Null hat.

Ich mache nichts Besonderes. Diese absolute Positionsplatzierung ist die Art und Weise, wie mein Ajax- Framework das Ein- und Ausblenden einiger Widgets implementiert.

Max
quelle
Ich gab auch eine Antwort auf diese 'doppelte' Frage: stackoverflow.com/questions/5353934/…
Tokimon

Antworten:

135

Hängt davon ab, wie Sie "Offscreen" definieren. Befindet sich das im Ansichtsfenster oder innerhalb der definierten Grenzen Ihrer Seite?

Mit Element.getBoundingClientRect () können Sie leicht erkennen, ob sich Ihr Element innerhalb der Grenzen Ihres Ansichtsfensters befindet (dh auf dem Bildschirm oder außerhalb des Bildschirms):

jQuery.expr.filters.offscreen = function(el) {
  var rect = el.getBoundingClientRect();
  return (
           (rect.x + rect.width) < 0 
             || (rect.y + rect.height) < 0
             || (rect.x > window.innerWidth || rect.y > window.innerHeight)
         );
};

Sie können das dann auf verschiedene Arten verwenden:

// returns all elements that are offscreen
$(':offscreen');

// boolean returned if element is offscreen
$('div').is(':offscreen');
Scurker
quelle
2
Ich mochte das, aber es bricht ab, wenn sich Ihr Element in einem scrollbaren Container befindet - ein Element am unteren Rand eines 2-Bildschirm-hohen DIV ist immer "außerhalb des Bildschirms", da die Fensterhöhe kleiner als die offsetTop des Elements ist.
Coderer
@scurker Ich konnte das nicht zum Laufen bringen. Hier ist meine SO-Frage (mit jsFiddle) zum Problem: stackoverflow.com/questions/26004098/…
Crashwap
irre ich mich hier zu denken, dass dies nicht der Fall ist, wenn el Eltern (absolut oder relativ) vor dem Körper positioniert hat?
Fekiri Malek
@fekirimalek Sie sind richtig, ich habe das Beispiel aktualisiert, um dies zu berücksichtigen
Scurker
7
Beachten Sie, dass dies derzeit (Januar 2017) zumindest in Chrome nicht funktioniert, da Element.getBoundingClientRect () anstelle von x und y die Eigenschaften oben, rechts, unten und links hat.
Asu
18

Hier gibt es ein jQuery-Plugin, mit dem Benutzer testen können, ob ein Element in das sichtbare Ansichtsfenster des Browsers fällt, wobei die Bildlaufposition des Browsers berücksichtigt wird.

$('#element').visible();

Sie können auch die teilweise Sichtbarkeit überprüfen:

$('#element').visible( true);

Ein Nachteil ist, dass es nur mit vertikaler Positionierung / Scrollen funktioniert, obwohl es einfach genug sein sollte, der Mischung eine horizontale Positionierung hinzuzufügen.

Sam Sehnert
quelle
Dies ist ein sehr leichtes Plugin. Ich war in der Lage, eine feste Navigationsleiste beim Scrollen nach oben zu bekommen und innerhalb von Minuten nach dem Hinzufügen reaktionsschnell zu arbeiten. Toller Vorschlag.
Nappstir
Dieses Plugin ist sehr leicht und recht einfach zu implementieren. Das Problem mit den Untermenüs wurde behoben.
Theo Orphanos
9

Es ist kein Plugin erforderlich, um zu überprüfen, ob es sich außerhalb des Ansichtsports befindet.

var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
var d = $(document).scrollTop();

$.each($("div"),function(){
    p = $(this).position();
    //vertical
    if (p.top > h + d || p.top > h - d){
        console.log($(this))
    }
    //horizontal
    if (p.left < 0 - $(this).width() || p.left > w){
        console.log($(this))
    }
});
Simon Hudin
quelle
1
Dies würde funktionieren, wenn Sie $(this).offsetanstelle von verwenden $this.position. Im Moment berechnet es nur die Entfernung von seinem Elternteil, was ein Div sein könnte, der es perfekt umhüllt.
Ryan Shillington
7

Nun ... Ich habe hier in jeder vorgeschlagenen Lösung einige Probleme gefunden.

  • Sie sollten auswählen können, ob das gesamte Element oder nur ein Teil davon auf dem Bildschirm angezeigt werden soll
  • Vorgeschlagene Lösungen schlagen fehl, wenn das Element höher / breiter als das Fenster ist und das Browserfenster irgendwie abdeckt .

Hier ist meine Lösung, die jQuery .fnInstanzfunktion und enthält expression. Ich habe mehr Variablen in meiner Funktion erstellt, als ich konnte, aber für komplexe logische Probleme teile ich sie gerne in kleinere, klar benannte Teile.

Ich verwende eine getBoundingClientRectMethode, die die Elementposition relativ zum Ansichtsfenster zurückgibt, sodass ich mich nicht um die Bildlaufposition kümmern muss

Verwendung :

$(".some-element").filter(":onscreen").doSomething();
$(".some-element").filter(":entireonscreen").doSomething();
$(".some-element").isOnScreen(); // true / false
$(".some-element").isOnScreen(true); // true / false (partially on screen)
$(".some-element").is(":onscreen"); // true / false (partially on screen)
$(".some-element").is(":entireonscreen"); // true / false 

Quelle :

$.fn.isOnScreen = function(partial){

    //let's be sure we're checking only one element (in case function is called on set)
    var t = $(this).first();

    //we're using getBoundingClientRect to get position of element relative to viewport
    //so we dont need to care about scroll position
    var box = t[0].getBoundingClientRect();

    //let's save window size
    var win = {
        h : $(window).height(),
        w : $(window).width()
    };

    //now we check against edges of element

    //firstly we check one axis
    //for example we check if left edge of element is between left and right edge of scree (still might be above/below)
    var topEdgeInRange = box.top >= 0 && box.top <= win.h;
    var bottomEdgeInRange = box.bottom >= 0 && box.bottom <= win.h;

    var leftEdgeInRange = box.left >= 0 && box.left <= win.w;
    var rightEdgeInRange = box.right >= 0 && box.right <= win.w;


    //here we check if element is bigger then window and 'covers' the screen in given axis
    var coverScreenHorizontally = box.left <= 0 && box.right >= win.w;
    var coverScreenVertically = box.top <= 0 && box.bottom >= win.h;

    //now we check 2nd axis
    var topEdgeInScreen = topEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );
    var bottomEdgeInScreen = bottomEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );

    var leftEdgeInScreen = leftEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );
    var rightEdgeInScreen = rightEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );

    //now knowing presence of each edge on screen, we check if element is partially or entirely present on screen
    var isPartiallyOnScreen = topEdgeInScreen || bottomEdgeInScreen || leftEdgeInScreen || rightEdgeInScreen;
    var isEntirelyOnScreen = topEdgeInScreen && bottomEdgeInScreen && leftEdgeInScreen && rightEdgeInScreen;

    return partial ? isPartiallyOnScreen : isEntirelyOnScreen;

};

$.expr.filters.onscreen = function(elem) {
  return $(elem).isOnScreen(true);
};

$.expr.filters.entireonscreen = function(elem) {
  return $(elem).isOnScreen(true);
};
pie6k
quelle
1
Ich erhalte make_footer_down.js: 8 Ungefangener TypeError: Die Eigenschaft 'getBoundingClientRect' von undefined kann nicht gelesen werden, wenn versucht wird, Ihre Funktionen dort zu verwenden.
Ludvig W
Hallo Lurr ... Ich habe es mit $ ("# divId") versucht. IsOnScreen (true); wo 'divId' außerhalb des Bildschirms war und es mir 'false' zurückgab;
Also
1
  • Ermitteln Sie den Abstand vom oberen Rand des angegebenen Elements
  • Fügen Sie die Höhe desselben Elements hinzu. Hier erfahren Sie die Gesamtzahl vom oberen Bildschirmrand bis zum Ende des angegebenen Elements.
  • Dann müssen Sie nur noch das von der gesamten Dokumenthöhe abziehen

    jQuery(function () {
        var documentHeight = jQuery(document).height();
        var element = jQuery('#you-element');
        var distanceFromBottom = documentHeight - (element.position().top + element.outerHeight(true));
        alert(distanceFromBottom)
    });
    
user5294803
quelle
-1

Sie können die Position des Div mit $(div).position()überprüfen und prüfen, ob die Eigenschaften für den linken und oberen Rand kleiner als 0 sind:

if($(div).position().left < 0 && $(div).position().top < 0){
    alert("off screen");
}
Troy Barlow
quelle
2
Was ist, wenn der Div nicht negativ ist?
Alter