2012-01-17 11 views
65

Muszę sprawdzić w jQuery, czy element DIV nie spada z ekranu. Elementy są widoczne i wyświetlona według atrybutów CSS, ale mogą one zostać celowo umieszczony poza ekranu:Jak sprawdzić, czy element jest poza ekranem?

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

nie może użyć jQuery :visible przełącznik jako element ma niezerową wysokość i szerokość.

Nie robię nic nadzwyczajnego. To absolutne położenie pozycji jest sposobem w jaki mój framework Ajax implementuje hide/show niektórych widżetów.

+0

dałem odpowiedź na to, jak dobrze na tym „duplikat” pytanie: http://stackoverflow.com/ pytania/5353934/check-if-element-is-visible-on-screen/5354536 # 5354536 – Tokimon

Odpowiedz

101

Zależy co twoja definicja „poza ekranem” jest. Czy to w oknie roboczym, czy w określonych granicach twojej strony?

Korzystanie Element.getBoundingClientRect() można łatwo wykryć, czy Twój elementem jest wewnątrz boundries swojego rzutni (tj ekranie lub poza ekranem):

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

Następnie można użyć tego na kilka sposobów:

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

// boolean returned if element is offscreen 
$('div').is(':offscreen'); 
+1

Podobało mi się to, ale się zepsuło, jeśli twój element znajduje się w przewijanym pojemniku - element na spodzie 2-poziomowego DIV zawsze będzie "poza ekranem", ponieważ wysokość okna jest mniejsza niż przesunięcie Top elementu. – Coderer

+0

@scurker Nie mogłem tego uruchomić. Oto moje pytanie SO (z jsFiddle) na temat problemu: http://stackoverflow.com/questions/26004098/extend-jquery-to-create-custom-filter-re-element-outside-viewport – crashwap

+0

czy jestem w błędzie tutaj myślę, że to nie będzie, jeśli el umieścił rodzic (absolutny lub względny) przed ciałem? –

-1

Można sprawdzić położenie div używając $(div).position() i sprawdź, czy lewy i górny margines właściwości są mniejsze niż 0:

if($(div).position().left < 0 && $(div).position().top < 0){ 
    alert("off screen"); 
} 
+2

Co zrobić, jeśli element div nie jest ujemny? – dude

16

Istnieje jQuery plugin here, który umożliwia użytkownikom sprawdzenie, czy element wchodzi w widoczną widoczność przeglądarki, biorąc pod uwagę pozycję przewijania przeglądarki.

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

Można również sprawdzić na częściowe widoczności:

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

Jedną wadą jest to, że działa tylko z pionowego pozycjonowania/przewijanie, choć powinno być na tyle proste, aby dodać poziomą pozycję w mix.

+0

To jest bardzo lekka wtyczka. Udało mi się uzyskać stały pasek nawigacyjny po przewinięciu do góry i działając w sposób responsywny w ciągu kilku minut od dodania go. Świetna sugestia. – Nappstir

+0

Ta wtyczka jest bardzo lekka i łatwa do wdrożenia. Rozwiązałem problem, który miałem z podmenu. –

3

stworzyłem a small plugin that does this i ma pewne elastyczne opcje (działa również przy zmianie rozmiaru okna przeglądarki).

+0

Jak usunąć klasę 'right-edge'? na tej stronie testowej [link] http://archeo.ecrc.pl/ element '.sub-menu', po zastosowaniu klasy' right-edge' nie jest usuwany po zmianie rozmiaru okna przeglądarki. – Daniel

+0

@Daniel Przepraszamy za szalenie późną odpowiedź. Ale to jest teraz naprawione :) –

7

Nie trzeba używać wtyczki do sprawdzania, czy port jest poza portem.

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

To działałoby, gdyby użyłeś '$ (this) .offset' zamiast' $ this.position'. W tej chwili jest to obliczenie odległości od jej rodzica, która może być divem, który doskonale je owija. –

1

Cóż ... Znalazłem kilka problemów w każdym proponowanego rozwiązania tutaj.

  • powinien mieć możliwość wyboru, czy chcesz cały element się na ekranie lub tylko jej części
  • Proponowane rozwiązania zawodzi jeśli elementem jest wyższa/szersza niż okno i trochę obejmuje okno przeglądarki:.

Oto moje rozwiązanie, które obejmuje funkcję instancji jQuery.fn i expression. Stworzyłem więcej zmiennych w mojej funkcji, niż mogłem, ale dla złożonego problemu logicznego lubię dzielić go na mniejsze, wyraźnie nazwane kawałki.

Używam getBoundingClientRect metodę, która zwraca pozycję elementu relatywnie do rzutni więc nie trzeba się martwić o pozycji przewijania

useage:

$(".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 

Źródło:

$.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); 
}; 
+0

Otrzymuję make_footer_down.js: 8 Uncaught TypeError: Nie można odczytać właściwości 'getBoundingClientRect' z undefined podczas próby użycia funkcji ur. – Lurr

+0

Cześć Lurr ... Próbowałem z $ ("# divId"). IsOnScreen (true); gdzie "divId" było poza ekranem i zwróciło mi "false"; więc czuję, że działa – Anirban

0
  • Uzyskaj odległość od góry danego elementu
  • Dodaj wysokość tego samego elementu. Spowoduje to wyświetlenie całkowitej liczby od górnej krawędzi ekranu do końca danego elementu.
  • Następnie wszystko co musisz zrobić, to odejmowanie, że od całkowitej wysokości dokumentu

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