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