Zależy, co rozumiesz przez widoczny. Jeśli masz na myśli, czy jest on aktualnie wyświetlany na stronie, biorąc pod uwagę pozycję przewijania, możesz obliczyć ją na podstawie przesunięcia elementów y i bieżącej pozycji przewijania.
roryf
18
Wyjaśnienie: Widoczne, jak w obrębie aktualnie wyświetlanego prostokąta. Widoczny, jak nie ukryty ani wyświetlany: brak? Widoczny, ponieważ nie kryje się za nim coś innego w kolejności Z?
Adam Wright,
6
jak w obecnie wyświetlanym prostokącie. Dzięki. Przeformułowano.
benzaita
2
Zauważ, że wszystkie odpowiedzi tutaj dają fałszywy wynik pozytywny dla elementów, które znajdują się poza widocznym obszarem ich elementu nadrzędnego (eh z ukrytym przepełnieniem), ale wewnątrz obszaru rzutni.
Andy E
1
Istnieje milion odpowiedzi, a większość z nich jest absurdalnie długa. Zobacz tutaj
dwuliniową
Odpowiedzi:
346
Aktualizacja: czas mija, podobnie jak nasze przeglądarki. Ta technika nie jest już zalecana i powinieneś skorzystać z rozwiązania Dana, jeśli nie potrzebujesz obsługiwać wersji Internet Explorera przed 7.
Oryginalne rozwiązanie (teraz nieaktualne):
Spowoduje to sprawdzenie, czy element jest całkowicie widoczny w bieżącej rzutni:
function elementInViewport(el){var top = el.offsetTop;var left = el.offsetLeft;var width = el.offsetWidth;var height = el.offsetHeight;while(el.offsetParent){
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;}return(
top >= window.pageYOffset &&
left >= window.pageXOffset &&(top + height)<=(window.pageYOffset + window.innerHeight)&&(left + width)<=(window.pageXOffset + window.innerWidth));}
Możesz to zmodyfikować, aby określić, czy jakaś część elementu jest widoczna w rzutni:
function elementInViewport2(el){var top = el.offsetTop;var left = el.offsetLeft;var width = el.offsetWidth;var height = el.offsetHeight;while(el.offsetParent){
el = el.offsetParent;
top += el.offsetTop;
left += el.offsetLeft;}return(
top <(window.pageYOffset + window.innerHeight)&&
left <(window.pageXOffset + window.innerWidth)&&(top + height)> window.pageYOffset &&(left + width)> window.pageXOffset
);}
Oryginalna opublikowana funkcja miała błąd. Musiałem zapisać szerokość / wysokość przed ponownym przypisaniem el ...
Prestaul
15
Co jeśli element żyje w przewijalnym div i przewinięty z widoku?
amartynov,
2
Zapoznaj się z nowszą wersją skryptu poniżej
Dan
1
Ciekawe też pytanie @ amartynov. Czy ktoś wie, jak po prostu stwierdzić, czy element jest ukryty z powodu przepełnienia elementu przodka? Bonus, jeśli można to wykryć niezależnie od tego, jak głęboko dziecko jest zagnieżdżone.
Eric Nguyen,
1
@deadManN rekurencja w DOM jest notorycznie powolna. To wystarczający powód, ale dostawcy przeglądarki stworzyli również getBoundingClientRectw celu znalezienia współrzędnych elementów ... Dlaczego nie mielibyśmy go użyć?
To rozwiązanie zostało przetestowane na Internet Explorerze 7 (i późniejszych), iOS 5 (i późniejszych) Safari, Android 2.0 (Eclair) i późniejszych, BlackBerry, Opera Mobile i Internet Explorer Mobile 9 .
function isElementInViewport (el){// Special bonus for those using jQueryif(typeof jQuery ==="function"&& el instanceof jQuery){
el = el[0];}var rect = el.getBoundingClientRect();return(
rect.top >=0&&
rect.left >=0&&
rect.bottom <=(window.innerHeight || document.documentElement.clientHeight)&&/* or $(window).height() */
rect.right <=(window.innerWidth || document.documentElement.clientWidth)/* or $(window).width() */);}
Jak używać:
Możesz być pewien, że podana powyżej funkcja zwraca poprawną odpowiedź w momencie jej wywołania, ale co z widocznością elementu śledzącego jako zdarzenia?
Umieść następujący kod na dole <body>tagu:
function onVisibilityChange(el, callback){var old_visible;returnfunction(){var visible = isElementInViewport(el);if(visible != old_visible){
old_visible = visible;if(typeof callback =='function'){
callback();}}}}var handler = onVisibilityChange(el,function(){/* Your code go here */});// jQuery
$(window).on('DOMContentLoaded load resize scroll', handler);/* // Non-jQuery
if (window.addEventListener) {
addEventListener('DOMContentLoaded', handler, false);
addEventListener('load', handler, false);
addEventListener('scroll', handler, false);
addEventListener('resize', handler, false);
} else if (window.attachEvent) {
attachEvent('onDOMContentLoaded', handler); // Internet Explorer 9+ :(
attachEvent('onload', handler);
attachEvent('onscroll', handler);
attachEvent('onresize', handler);
}
*/
Jeśli dokonasz jakichkolwiek modyfikacji DOM, mogą one oczywiście zmienić widoczność Twojego elementu.
Wytyczne i typowe pułapki:
Może potrzebujesz śledzić powiększenie strony / uszczypnięcie urządzenia mobilnego? jQuery powinien obsługiwać przeglądarkę Zoom / Pinch w różnych przeglądarkach, w przeciwnym razie pierwszy lub drugi link powinien ci pomóc.
Jeśli zmodyfikujesz DOM , może to wpłynąć na widoczność elementu. Powinieneś przejąć nad tym kontrolę i zadzwonić handler()ręcznie. Niestety nie mamy żadnych onrepaintwydarzeń w różnych przeglądarkach . Z drugiej strony pozwala nam to na optymalizacje i ponowne sprawdzenie tylko tych modyfikacji DOM, które mogą zmienić widoczność elementu.
Nigdy nie używaj go tylko w jQuery $ (dokument) .ready () , ponieważ w tej chwili nie ma gwarancji CSS . Twój kod może współpracować lokalnie z CSS na dysku twardym, ale po umieszczeniu na zdalnym serwerze zawiedzie.
Nie możemy jeszcze złapać zdarzenia powiększenia / uszczypnięcia.
Ostatnim rozwiązaniem może być następujący kod:
/* TODO: this looks like a very bad code */
setInterval(handler,600);
Możesz skorzystać z niesamowitej strony funkcji Visiiliili interfejsu API HTML5, jeśli zależy Ci na tym, czy karta z twoją stroną jest aktywna i widoczna.
DO ZROBIENIA: ta metoda nie obsługuje dwóch sytuacji:
Korzystam z tego rozwiązania (uważaj jednak na literówkę „botom”). Jest też coś, o czym należy pamiętać, gdy rozważany element zawiera w sobie obrazy. Chrome (przynajmniej) musi poczekać, aż obraz zostanie załadowany, aby mieć dokładną wartość granicznego prostokąta. Wygląda na to, że Firefox nie ma tego „problemu”
Claudio,
4
Czy to działa, gdy masz włączone przewijanie w kontenerze wewnątrz ciała. Na przykład nie działa tutaj - agaase.github.io/webpages/demo/isonscreen2.html isElementInViewport (document.getElementById („innerele”)). innerele jest obecny w kontenerze z włączonym przewijaniem.
agaase,
70
Obliczenia zakładają, że element jest mniejszy niż ekran. Jeśli masz wysokie lub szerokie elementy, może być bardziej dokładny w użyciureturn (rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerWidth || document.documentElement.clientWidth));
Roonaan
11
Wskazówka: dla tych, którzy próbują to zaimplementować za pomocą jQuery, wystarczy przyjazne przypomnienie, aby przekazać obiekt HTML DOM (np. isElementInViewport(document.getElementById('elem'))), A nie obiekt jQuery (np isElementInViewport($("#elem)).). Równowartość jQuery jest dodanie [0]tak: isElementInViewport($("#elem)[0]).
Lepsza wydajność niż słuchanie zdarzeń przewijania
Działa w ramach iframe między domenami
Potrafi stwierdzić, czy element przeszkadza / przecina inny
Intersection Observer jest na dobrej drodze, aby stać się pełnoprawnym standardem i jest już obsługiwany w Chrome 51+, Edge 15+ i Firefox 55+ i jest w fazie rozwoju dla Safari. Dostępna jest również polifill .
Poprzednia odpowiedź
Istnieją pewne problemy z odpowiedzią udzieloną przez Dana, które mogą sprawić, że będzie to nieodpowiednie podejście w niektórych sytuacjach. Niektóre z tych problemów są wskazane w jego odpowiedzi u dołu, że jego kod da fałszywe trafienia dla elementów, które są:
Ukryty przez inny element przed testowanym
Poza widocznym obszarem elementu nadrzędnego lub przodka
Element lub jego dzieci ukryte za pomocą clipwłaściwości CSS
Ograniczenia te zostały przedstawione w następujących wynikach prostego testu :
Rozwiązanie: isElementVisible()
Oto rozwiązanie tych problemów, z poniższym wynikiem testu i objaśnieniem niektórych części kodu.
function isElementVisible(el){var rect = el.getBoundingClientRect(),
vWidth = window.innerWidth || document.documentElement.clientWidth,
vHeight = window.innerHeight || document.documentElement.clientHeight,
efp =function(x, y){return document.elementFromPoint(x, y)};// Return false if it's not in the viewportif(rect.right <0|| rect.bottom <0|| rect.left > vWidth || rect.top > vHeight)returnfalse;// Return true if any of its four corners are visiblereturn(
el.contains(efp(rect.left, rect.top))|| el.contains(efp(rect.right, rect.top))|| el.contains(efp(rect.right, rect.bottom))|| el.contains(efp(rect.left, rect.bottom)));}
Ta metoda nie jest jednak pozbawiona własnych ograniczeń. Na przykład element testowany z niższym indeksem Z niż inny element w tym samym miejscu zostałby zidentyfikowany jako ukryty, nawet jeśli element z przodu faktycznie nie ukrywa żadnej jego części. Mimo to metoda ta ma zastosowanie w niektórych przypadkach, których rozwiązanie Dana nie obejmuje.
Zarówno element.getBoundingClientRect()i document.elementFromPoint()są częścią projektu specyfikacji CSSOM roboczej i są obsługiwane w co najmniej IE 6 i nowszych, a większość przeglądarek pulpitu przez długi czas (choć nie idealnie). Zobacz Quirksmode na temat tych funkcji, aby uzyskać więcej informacji.
contains()służy do sprawdzenia, czy zwracany element document.elementFromPoint()jest węzłem potomnym elementu, który testujemy pod kątem widoczności. Zwraca również wartość true, jeśli zwracany element jest tym samym elementem. Dzięki temu czek jest bardziej niezawodny. Jest obsługiwany we wszystkich głównych przeglądarkach, a Firefox 9.0 jest ostatnim z nich, aby go dodać. Aby uzyskać starszą obsługę Firefoksa, sprawdź historię tej odpowiedzi.
Jeśli chcesz przetestować więcej punktów wokół elementu pod kątem widoczności ―, tj. Aby upewnić się, że element nie jest objęty więcej niż, powiedzmy, 50% ―, nie zajęłoby wiele, aby dopasować ostatnią część odpowiedzi. Pamiętaj jednak, że prawdopodobnie sprawdziłby się każdy piksel, aby upewnić się, że jest w 100% widoczny.
Czy miałeś na myśli użyć doc.documentElement.clientWidth? Czy zamiast tego powinien to być „document.documentElement”? Z drugiej strony, jest to jedyna metoda, która działa również w przypadkach użycia, takich jak ukrywanie zawartości elementu dla ułatwienia dostępu za pomocą właściwości CSS „clip”: snook.ca/archives/html_and_css/hiding-content-for-accessibility
Kevin Lamping
@klamping: dobry połów, dzięki. Skopiowałem go bezpośrednio z mojego kodu, którego używałem docjako aliasu document. Tak, lubię myśleć o tym jako o przyzwoitym rozwiązaniu w przypadku skrzynek.
Andy E
2
Dla mnie to nie działa. Ale inViewport () w poprzedniej odpowiedzi działa w FF.
Satya Prakash,
9
Korzystne może być również sprawdzenie, czy środek elementu jest widoczny, jeśli zastosowano zaokrąglone narożniki lub zastosowano transformację, ponieważ narożniki ograniczające mogą nie zwrócić oczekiwanego elementu:element.contains(efp(rect.right - (rect.width / 2), rect.bottom - (rect.height / 2)))
Jared,
2
Dla mnie nie działał na wejściach (chrom kanarek 50). Nie wiesz, dlaczego, może rodzime zaokrąglone rogi? Musiałem nieznacznie zmniejszyć kable, aby działał el. Zawiera (efp (rect.left + 1, rect.top + 1)) || el.contains (efp (rect.right-1, rect.top + 1)) || el. zawiera (efp (rect.right-1, rect.bottom-1)) || el.contains (efp (rect.left + 1, rect.bottom-1))
Rayjax
65
Próbowałem odpowiedzi Dana . Jednak algebra zastosowana do określenia granic oznacza, że element musi być zarówno ≤ wielkości rzutni, jak i całkowicie wewnątrz rzutni, aby uzyskać true, co łatwo prowadzi do fałszywych negatywów. Jeśli chcesz ustalić, czy element jest w ogóle w rzutni, odpowiedź Ryanve jest bliska, ale testowany element powinien nakładać się na rzutnię, więc spróbuj tego:
function isElementInViewport(el){var rect = el.getBoundingClientRect();return rect.bottom >0&&
rect.right >0&&
rect.left <(window.innerWidth || document.documentElement.clientWidth)/* or $(window).width() */&&
rect.top <(window.innerHeight || document.documentElement.clientHeight)/* or $(window).height() */;}
Jako usługa publiczna:
odpowiedź Dana z poprawnymi obliczeniami (elementem może być> okno, szczególnie na ekranach telefonów komórkowych) i poprawne testowanie jQuery, a także dodanie isElementPartIALInViewport:
Nawiasem mówiąc, różnica między window.innerWidth i document.documentElement.clientWidth polega na tym, że clientWidth / clientHeight nie zawiera paska przewijania, podczas gdy window.innerWidth / Height.
function isElementPartiallyInViewport(el){// Special bonus for those using jQueryif(typeof jQuery !=='undefined'&& el instanceof jQuery)
el = el[0];var rect = el.getBoundingClientRect();// DOMRect { x: 8, y: 8, width: 100, height: 100, top: 8, right: 108, bottom: 108, left: 8 }var windowHeight =(window.innerHeight || document.documentElement.clientHeight);var windowWidth =(window.innerWidth || document.documentElement.clientWidth);// http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlapvar vertInView =(rect.top <= windowHeight)&&((rect.top + rect.height)>=0);var horInView =(rect.left <= windowWidth)&&((rect.left + rect.width)>=0);return(vertInView && horInView);}// http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewportfunction isElementInViewport (el){// Special bonus for those using jQueryif(typeof jQuery !=='undefined'&& el instanceof jQuery)
el = el[0];var rect = el.getBoundingClientRect();var windowHeight =(window.innerHeight || document.documentElement.clientHeight);var windowWidth =(window.innerWidth || document.documentElement.clientWidth);return((rect.left >=0)&&(rect.top >=0)&&((rect.left + rect.width)<= windowWidth)&&((rect.top + rect.height)<= windowHeight));}function fnIsVis(ele){var inVpFull = isElementInViewport(ele);var inVpPartial = isElementPartiallyInViewport(ele);
console.clear();
console.log("Fully in viewport: "+ inVpFull);
console.log("Partially in viewport: "+ inVpPartial);}
isElementPartiallyInViewportjest również bardzo przydatny. Niezłe.
RJ Cuthbertson
Dla isElementInViewport (e): Twój kod nie ładuje nawet obrazów, Ten jest poprawny: funkcja isElementInViewport (e) {var t = e.getBoundingClientRect (); return t.top> = 0 && t.left> = 0 && t.bottom <= (window.innerHeight || document.documentElement.clientHeight) && t.right <= (window.innerWidth || document.documentElement.clientWidth) }
Arun chauhan,
1
@Arun chauhan: Żaden z moich kodów nie ładuje obrazów, więc dlaczego powinienem, a formuła jest poprawna.
Stefan Steiger,
1
@targumon: Powodem jest obsługa starych przeglądarek.
Stefan Steiger
1
@StefanSteiger według MDN jest obsługiwany od IE9, więc praktycznie (przynajmniej w moim przypadku) jest bezpieczne bezpośrednie użycie window.innerHeight. Dzięki!
Moje rozwiązanie jest bardziej chciwe i szybsze, gdy element ma piksel w polu wyświetlania, zwróci wartość false.
Eric Chen
1
Lubię to. Zwięzły. Możesz usunąć spacje między nazwą funkcji a nawiasami oraz między nawiasami i nawiasami, w pierwszym wierszu. Nigdy nie lubiłem tych przestrzeni. Może to tylko mój edytor tekstu koduje to wszystko, co wciąż ułatwia czytanie. function aaa (arg) {instrukcje} Wiem, że to nie przyspiesza jego działania, zamiast tego podlega niedozwoleniu.
YK
21
Niepokoiło mnie to, że nie było dostępnej dla jQuery wersji funkcjonalności. Kiedy natknąłem się na rozwiązanie Dana, zauważyłem możliwość zapewnienia czegoś dla ludzi, którzy lubią programować w stylu jQuery OO. Jest miły i zgryźliwy i działa jak urok dla mnie.
Bada bing bada boom
$.fn.inView =function(){if(!this.length)returnfalse;var rect =this.get(0).getBoundingClientRect();return(
rect.top >=0&&
rect.left >=0&&
rect.bottom <=(window.innerHeight || document.documentElement.clientHeight)&&
rect.right <=(window.innerWidth || document.documentElement.clientWidth));};// Additional examples for other use cases// Is true false whether an array of elements are all in view
$.fn.allInView =function(){var all =[];this.forEach(function(){
all.push( $(this).inView());});return all.indexOf(false)===-1;};// Only the class elements in view
$('.some-class').filter(function(){return $(this).inView();});// Only the class elements not in view
$('.some-class').filter(function(){return!$(this).inView();});
Stosowanie
$(window).on('scroll',function(){if( $('footer').inView()){// Do cool stuff}});
To rozwiązanie będzie wymagało wypełniania polifill, ponieważ Safari, Opera i Internet Explorer nie obsługują tego jeszcze (wypełnienie jest zawarte w rozwiązaniu).
W tym rozwiązaniu pole jest poza polem widzenia, które jest celem (obserwowanym). Jeśli chodzi o widok, przycisk u góry nagłówka jest ukryty. Jest pokazywany, gdy pudełko opuści widok.
const buttonToHide = document.querySelector('button');const hideWhenBoxInView =newIntersectionObserver((entries)=>{if(entries[0].intersectionRatio <=0){// If not in view
buttonToHide.style.display ="inherit";}else{
buttonToHide.style.display ="none";}});
hideWhenBoxInView.observe(document.getElementById('box'));
<scriptsrc="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script><header><button>NAVIGATION BUTTON TO HIDE</button></header><divclass="wrapper"><divid="box"></div></div>
Dobra realizacja, a według link w tej odpowiedzi nie powinien pracować na safari przez dodanie <!DOCTYPE html>do HTML
Alon Eitan
Pamiętaj, że IntersectionObserverjest to funkcja eksperymentalna (która może ulec zmianie w przyszłości).
Karthik Chintala
2
@KarthikChintala - jest obsługiwany w każdej przeglądarce z wyjątkiem IE - i jest również dostępna polifill.
Randy Casburn
Nie rozwiązuje pytania PO, ponieważ wykrywa tylko zmiany : IntersectionObserverwyzwala tylko oddzwonienie po ruchu celu względem korzenia.
Brandon Hill,
Po wywołaniu observezdarzenia natychmiast zostaje wyzwolony komunikat informujący o bieżącym stanie przecięcia śledzonego elementu. Tak więc, w jakiś sposób - dotyczy.
Mesqalito
8
Wszystkie odpowiedzi, które tu napotkałem, sprawdzają tylko, czy element jest umieszczony w bieżącej rzutni . Ale to nie znaczy, że jest widoczne .
Co jeśli dany element znajduje się w div z przepełnioną zawartością i jest przewijany poza pole widzenia?
Aby rozwiązać ten problem, musisz sprawdzić, czy element jest zawarty przez wszystkich rodziców.
Moje rozwiązanie robi dokładnie to:
Pozwala także określić, jak duży element ma być widoczny.
Element.prototype.isVisible =function(percentX, percentY){var tolerance =0.01;//needed because the rects returned by getBoundingClientRect provide the position up to 10 decimalsif(percentX ==null){
percentX =100;}if(percentY ==null){
percentY =100;}var elementRect =this.getBoundingClientRect();var parentRects =[];var element =this;while(element.parentElement !=null){
parentRects.push(element.parentElement.getBoundingClientRect());
element = element.parentElement;}var visibleInAllParents = parentRects.every(function(parentRect){var visiblePixelX =Math.min(elementRect.right, parentRect.right)-Math.max(elementRect.left, parentRect.left);var visiblePixelY =Math.min(elementRect.bottom, parentRect.bottom)-Math.max(elementRect.top, parentRect.top);var visiblePercentageX = visiblePixelX / elementRect.width *100;var visiblePercentageY = visiblePixelY / elementRect.height *100;return visiblePercentageX + tolerance > percentX && visiblePercentageY + tolerance > percentY;});return visibleInAllParents;};
To rozwiązanie zignorowało fakt, że elementy mogą nie być widoczne z powodu innych faktów, takich jak opacity: 0.
Przetestowałem to rozwiązanie w Chrome i Internet Explorer 11.
Uważam, że przyjęta tutaj odpowiedź jest zbyt skomplikowana w przypadku większości przypadków użycia. Ten kod dobrze wykonuje zadanie (używając jQuery) i rozróżnia elementy w pełni widoczne i częściowo widoczne:
var element = $("#element");var topOfElement = element.offset().top;var bottomOfElement = element.offset().top + element.outerHeight(true);var $window = $(window);
$window.bind('scroll',function(){var scrollTopPosition = $window.scrollTop()+$window.height();var windowScrollTop = $window.scrollTop()if(windowScrollTop > topOfElement && windowScrollTop < bottomOfElement){// Element is partially visible (above viewable area)
console.log("Element is partially visible (above viewable area)");}elseif(windowScrollTop > bottomOfElement && windowScrollTop > topOfElement){// Element is hidden (above viewable area)
console.log("Element is hidden (above viewable area)");}elseif(scrollTopPosition < topOfElement && scrollTopPosition < bottomOfElement){// Element is hidden (below viewable area)
console.log("Element is hidden (below viewable area)");}elseif(scrollTopPosition < bottomOfElement && scrollTopPosition > topOfElement){// Element is partially visible (below viewable area)
console.log("Element is partially visible (below viewable area)");}else{// Element is completely visible
console.log("Element is completely visible");}});
Jak to działa w przeglądarkach mobilnych? Większość z nich ma problem z wyświetlaniem, nagłówek przewija się w górę lub w dół podczas przewijania, a inne zachowanie pojawia się, gdy pojawia się klawiatura, w zależności od tego, czy jest to Android, iOS itp.
Kev
@ Kev Powinno działać dobrze, w zależności od tego, kiedy wywołasz tę metodę. Jeśli go wywołasz, a następnie zmienisz rozmiar okna, wynik może oczywiście nie być poprawny. Możesz to nazwać przy każdym zdarzeniu zmiany rozmiaru w zależności od rodzaju pożądanej funkcjonalności. Zadaj osobne pytanie dotyczące konkretnego przypadku użycia i ping mnie tutaj.
leonheess
3
Myślę, że jest to bardziej funkcjonalny sposób na zrobienie tego.
Odpowiedź Dana nie działa w kontekście rekurencyjnym.
Ta funkcja rozwiązuje problem, gdy element znajduje się wewnątrz innych przewijalnych div div, testując rekursywnie wszystkie poziomy aż do znacznika HTML, i zatrzymuje się przy pierwszym false.
/**
* fullVisible=true only returns true if the all object rect is visible
*/function isReallyVisible(el, fullVisible){if( el.tagName =="HTML")returntrue;var parentRect=el.parentNode.getBoundingClientRect();var rect = arguments[2]|| el.getBoundingClientRect();return(( fullVisible ? rect.top >= parentRect.top : rect.bottom > parentRect.top )&&( fullVisible ? rect.left >= parentRect.left : rect.right > parentRect.left )&&( fullVisible ? rect.bottom <= parentRect.bottom : rect.top < parentRect.bottom )&&( fullVisible ? rect.right <= parentRect.right : rect.left < parentRect.right )&&
isReallyVisible(el.parentNode, fullVisible, rect));};
Najczęściej akceptowane odpowiedzi nie działają podczas powiększania w Google Chrome na Androida. W połączeniu z odpowiedzią Dana , aby uwzględnić Chrome na Androida, należy użyć visualViewport . Poniższy przykład uwzględnia tylko sprawdzenie pionowe i używa jQuery dla wysokości okna:
var visibleY =function(el){var top = el.getBoundingClientRect().top, rect, el = el.parentNode;do{
rect = el.getBoundingClientRect();if(top <= rect.bottom ===false)returnfalse;
el = el.parentNode;}while(el != document.body);// Check it's within the document viewportreturn top <= document.documentElement.clientHeight;};
Musiałem tylko sprawdzić, czy jest widoczny na osi Y (dla przewijanej funkcji ładowania więcej rekordów Ajax).
Używam go w ten sposób, że gdy element przewija się do widoku, dodaję klasę, która wyzwala animację klatki kluczowej CSS. Jest to dość proste i działa szczególnie dobrze, gdy masz ponad 10 rzeczy warunkowo animowanych na stronie.
Zdecydowanie powinieneś buforować $window = $(window)poza
modułem
2
Większość zwyczajów z poprzednich odpowiedzi kończy się niepowodzeniem w następujących punktach:
- Gdy widoczny jest dowolny piksel elementu, ale nie „ narożnik ”,
-Gdy element jest większy niż rzutnia i wyśrodkowany ,
-Większość z nich sprawdza tylko pojedynczy element w dokumencie lub oknie .
Cóż, dla wszystkich tych problemów mam rozwiązanie, a plusy to:
-Możesz powrócić, visiblegdy pojawi się tylko piksel z dowolnej strony i nie jest to narożnik,
- Nadal możesz powrócić, visiblegdy element jest większy niż rzutnia,
-Możesz wybrać swój parent element lub możesz automatycznie pozwolić mu wybrać,
- Działa również na dynamicznie dodawanych elementach .
Jeśli sprawdzisz poniższe fragmenty, zobaczysz różnicę w użyciu overflow-scrollw kontenerze elementu nie spowoduje żadnych problemów i zobaczysz, że w przeciwieństwie do innych odpowiedzi tutaj, nawet jeśli piksel pojawia się z dowolnej strony lub gdy element jest większy niż obszar wyświetlania i widzimy wnętrze piksele elementu, który nadal działa.
Użycie jest proste:
// For checking element visibility from any sides
isVisible(element)// For checking elements visibility in a parent you would like to checkvar parent = document;// Assuming you check if 'element' inside 'document'
isVisible(element, parent)// For checking elements visibility even if it's bigger than viewport
isVisible(element,null,true)// Without parent choice
isVisible(element, parent,true)// With parent choice
Demonstracja, bez crossSearchAlgorithmktórej jest przydatna dla elementów większych niż element kontrolny rzutni 3 wewnętrzne piksele, aby zobaczyć:
function isVisible(element, parent, crossSearchAlgorithm){var rect = element.getBoundingClientRect(),
prect =(parent !=undefined)? parent.getBoundingClientRect(): element.parentNode.getBoundingClientRect(),
csa =(crossSearchAlgorithm !=undefined)? crossSearchAlgorithm :false,
efp =function(x, y){return document.elementFromPoint(x, y)};// Return false if it's not in the viewportif(rect.right < prect.left || rect.bottom < prect.top || rect.left > prect.right || rect.top > prect.bottom){returnfalse;}var flag =false;// Return true if left to right any border pixel reachedfor(var x = rect.left; x < rect.right; x++){if(element.contains(efp(rect.top, x))|| element.contains(efp(rect.bottom, x))){
flag =true;break;}}// Return true if top to bottom any border pixel reachedif(flag ==false){for(var y = rect.top; y < rect.bottom; y++){if(element.contains(efp(rect.left, y))|| element.contains(efp(rect.right, y))){
flag =true;break;}}}if(csa){// Another algorithm to check if element is centered and bigger than viewportif(flag ==false){var x = rect.left;var y = rect.top;// From top left to bottom rightwhile(x < rect.right || y < rect.bottom){if(element.contains(efp(x,y))){
flag =true;break;}if(x < rect.right){ x++;}if(y < rect.bottom){ y++;}}if(flag ==false){
x = rect.right;
y = rect.top;// From top right to bottom leftwhile(x > rect.left || y < rect.bottom){if(element.contains(efp(x,y))){
flag =true;break;}if(x > rect.left){ x--;}if(y < rect.bottom){ y++;}}}}}return flag;}// Check multiple elements visibility
document.getElementById('container').addEventListener("scroll",function(){var elementList = document.getElementsByClassName("element");var console = document.getElementById('console');for(var i=0; i < elementList.length; i++){// I did not define parent, so it will be element's parentif(isVisible(elementList[i])){
console.innerHTML ="Element with id["+ elementList[i].id +"] is visible!";break;}else{
console.innerHTML ="Element with id["+ elementList[i].id +"] is hidden!";}}});// Dynamically added elementsfor(var i=4; i <=6; i++){var newElement = document.createElement("div");
newElement.id ="element"+ i;
newElement.classList.add("element");
document.getElementById('container').appendChild(newElement);}
Widzisz, gdy jesteś w elemencie3 , nie określa , czy jest widoczny, czy nie, ponieważ sprawdzamy tylko, czy element jest widoczny z boku lub z narożników .
I ta zawiera, crossSearchAlgorithmktóra pozwala ci wrócić, visiblegdy element jest większy niż rzutnia:
function isVisible(element, parent, crossSearchAlgorithm){var rect = element.getBoundingClientRect(),
prect =(parent !=undefined)? parent.getBoundingClientRect(): element.parentNode.getBoundingClientRect(),
csa =(crossSearchAlgorithm !=undefined)? crossSearchAlgorithm :false,
efp =function(x, y){return document.elementFromPoint(x, y)};// Return false if it's not in the viewportif(rect.right < prect.left || rect.bottom < prect.top || rect.left > prect.right || rect.top > prect.bottom){returnfalse;}var flag =false;// Return true if left to right any border pixel reachedfor(var x = rect.left; x < rect.right; x++){if(element.contains(efp(rect.top, x))|| element.contains(efp(rect.bottom, x))){
flag =true;break;}}// Return true if top to bottom any border pixel reachedif(flag ==false){for(var y = rect.top; y < rect.bottom; y++){if(element.contains(efp(rect.left, y))|| element.contains(efp(rect.right, y))){
flag =true;break;}}}if(csa){// Another algorithm to check if element is centered and bigger than viewportif(flag ==false){var x = rect.left;var y = rect.top;// From top left to bottom rightwhile(x < rect.right || y < rect.bottom){if(element.contains(efp(x,y))){
flag =true;break;}if(x < rect.right){ x++;}if(y < rect.bottom){ y++;}}if(flag ==false){
x = rect.right;
y = rect.top;// From top right to bottom leftwhile(x > rect.left || y < rect.bottom){if(element.contains(efp(x,y))){
flag =true;break;}if(x > rect.left){ x--;}if(y < rect.bottom){ y++;}}}}}return flag;}// Check multiple elements visibility
document.getElementById('container').addEventListener("scroll",function(){var elementList = document.getElementsByClassName("element");var console = document.getElementById('console');for(var i=0; i < elementList.length; i++){// I did not define parent so it will be element's parent// and it will do crossSearchAlgorithmif(isVisible(elementList[i],null,true)){
console.innerHTML ="Element with id["+ elementList[i].id +"] is visible!";break;}else{
console.innerHTML ="Element with id["+ elementList[i].id +"] is hidden!";}}});// Dynamically added elementsfor(var i=4; i <=6; i++){var newElement = document.createElement("div");
newElement.id ="element"+ i;
newElement.classList.add("element");
document.getElementById('container').appendChild(newElement);}
Ten kod ma na celu uzyskanie dokładniejszych informacji, jeśli jakaś część elementu jest pokazana w widoku, czy nie. Aby korzystać z opcji wydajności lub tylko pionowych slajdów, nie używaj tego! Ten kod jest bardziej skuteczny w rysowaniu przypadków.
Powinieneś spróbować wyjaśnić, dlaczego Twoja wersja jest lepsza. Na obecnym etapie wygląda mniej więcej tak samo jak inne rozwiązania.
Andy E
1
Świetne rozwiązanie, ma BOX / ScrollContainer i nie używa WINDOW (tylko jeśli nie jest określony). Spójrz na kod niż oceń, jest to bardziej uniwersalne rozwiązanie (często go
szukałem
1
Tak proste, jak to tylko możliwe, IMO:
function isVisible(elem){var coords = elem.getBoundingClientRect();returnMath.abs(coords.top)<= coords.height;}
Miałem to samo pytanie i rozgryzłem je za pomocą getBoundingClientRect ().
Ten kod jest całkowicie „ogólny” i musi być napisany tylko raz, aby zadziałał (nie musisz go pisać dla każdego elementu, który chcesz wiedzieć, jest w okienku ekranu).
Ten kod sprawdza tylko, czy jest pionowo w rzutni, a nie w poziomie . W tym przypadku „elementy” zmiennej (tablicy) przechowują wszystkie elementy, które sprawdzasz, aby były pionowo w rzutni, więc chwyć dowolne elementy w dowolnym miejscu i przechowuj je tam.
„Pętla for” zapętla każdy element i sprawdza, czy znajduje się on pionowo w rzutni. Ten kod jest wykonywany za każdym razem, gdy użytkownik przewija! Jeśli getBoudingClientRect (). Top ma mniej niż 3/4 rzutni (element ma jedną czwartą w rzutni), rejestruje się jako „w rzutni”.
Ponieważ kod jest ogólny, będziesz chciał wiedzieć, który element znajduje się w rzutni. Aby się tego dowiedzieć, możesz to ustalić na podstawie niestandardowego atrybutu, nazwy węzła, identyfikatora, nazwy klasy i innych kryteriów.
Oto mój kod (powiedz mi, jeśli nie działa; został przetestowany w Internet Explorer 11, Firefox 40.0.3, Chrome Wersja 45.0.2454.85 m, Opera 31.0.1889.174 i Edge z Windows 10, [jeszcze nie Safari ]) ...
// Scrolling handlers...
window.onscroll =function(){var elements = document.getElementById('whatever').getElementsByClassName('whatever');for(var i =0; i != elements.length; i++){if(elements[i].getBoundingClientRect().top <= window.innerHeight*0.75&&
elements[i].getBoundingClientRect().top >0){
console.log(elements[i].nodeName +' '+
elements[i].className +' '+
elements[i].id +' is in the viewport; proceed with whatever code you want to do here.');}};
Wszystkie odpowiedzi tutaj określają, czy element jest całkowicie zawarty w rzutni, a nie tylko w jakiś sposób widoczny. Na przykład, jeśli tylko połowa obrazu jest widoczna u dołu widoku, rozwiązania tutaj zawiodą, biorąc pod uwagę, że „na zewnątrz”.
Miałem przypadek użycia, w którym ładuję się leniwie IntersectionObserver, ale z powodu animacji pojawiających się podczas wyskakującego okienka nie chciałem oglądać żadnych obrazów, które były już przecinane podczas ładowania strony. Aby to zrobić, użyłem następującego kodu:
Jest to w zasadzie sprawdzenie, czy górna lub dolna granica jest niezależnie w rzutni. Przeciwny koniec może znajdować się na zewnątrz, ale dopóki jeden jest w środku, jest „widoczny” co najmniej częściowo.
Odpowiedzi:
Aktualizacja: czas mija, podobnie jak nasze przeglądarki. Ta technika nie jest już zalecana i powinieneś skorzystać z rozwiązania Dana, jeśli nie potrzebujesz obsługiwać wersji Internet Explorera przed 7.
Oryginalne rozwiązanie (teraz nieaktualne):
Spowoduje to sprawdzenie, czy element jest całkowicie widoczny w bieżącej rzutni:
Możesz to zmodyfikować, aby określić, czy jakaś część elementu jest widoczna w rzutni:
źródło
getBoundingClientRect
w celu znalezienia współrzędnych elementów ... Dlaczego nie mielibyśmy go użyć?Teraz większość przeglądarek obsługuje metodę getBoundingClientRect , która stała się najlepszą praktyką. Użycie starej odpowiedzi jest bardzo wolne , niedokładne i zawiera kilka błędów .
Rozwiązanie wybrane jako prawidłowe prawie nigdy nie jest precyzyjne . Możesz przeczytać więcej o jego błędach.
To rozwiązanie zostało przetestowane na Internet Explorerze 7 (i późniejszych), iOS 5 (i późniejszych) Safari, Android 2.0 (Eclair) i późniejszych, BlackBerry, Opera Mobile i Internet Explorer Mobile 9 .
Jak używać:
Możesz być pewien, że podana powyżej funkcja zwraca poprawną odpowiedź w momencie jej wywołania, ale co z widocznością elementu śledzącego jako zdarzenia?
Umieść następujący kod na dole
<body>
tagu:Jeśli dokonasz jakichkolwiek modyfikacji DOM, mogą one oczywiście zmienić widoczność Twojego elementu.
Wytyczne i typowe pułapki:
Może potrzebujesz śledzić powiększenie strony / uszczypnięcie urządzenia mobilnego? jQuery powinien obsługiwać przeglądarkę Zoom / Pinch w różnych przeglądarkach, w przeciwnym razie pierwszy lub drugi link powinien ci pomóc.
Jeśli zmodyfikujesz DOM , może to wpłynąć na widoczność elementu. Powinieneś przejąć nad tym kontrolę i zadzwonić
handler()
ręcznie. Niestety nie mamy żadnychonrepaint
wydarzeń w różnych przeglądarkach . Z drugiej strony pozwala nam to na optymalizacje i ponowne sprawdzenie tylko tych modyfikacji DOM, które mogą zmienić widoczność elementu.Nigdy nie używaj go tylko w jQuery $ (dokument) .ready () , ponieważ w tej chwili nie ma gwarancji CSS . Twój kod może współpracować lokalnie z CSS na dysku twardym, ale po umieszczeniu na zdalnym serwerze zawiedzie.
Po
DOMContentLoaded
wystrzeleniu, style są stosowane , ale zdjęcia nie są jeszcze załadowany . Powinniśmy dodaćwindow.onload
detektor zdarzeń.Nie możemy jeszcze złapać zdarzenia powiększenia / uszczypnięcia.
Ostatnim rozwiązaniem może być następujący kod:
Możesz skorzystać z niesamowitej strony funkcji Visiiliili interfejsu API HTML5, jeśli zależy Ci na tym, czy karta z twoją stroną jest aktywna i widoczna.
DO ZROBIENIA: ta metoda nie obsługuje dwóch sytuacji:
z-index
overflow-scroll
w kontenerze elementuźródło
return (rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerWidth || document.documentElement.clientWidth));
isElementInViewport(document.getElementById('elem'))
), A nie obiekt jQuery (npisElementInViewport($("#elem))
.). Równowartość jQuery jest dodanie[0]
tak:isElementInViewport($("#elem)[0])
.el is not defined
Aktualizacja
W nowoczesnych przeglądarkach warto sprawdzić interfejs API Intersection Observer, który zapewnia następujące korzyści:
Intersection Observer jest na dobrej drodze, aby stać się pełnoprawnym standardem i jest już obsługiwany w Chrome 51+, Edge 15+ i Firefox 55+ i jest w fazie rozwoju dla Safari. Dostępna jest również polifill .
Poprzednia odpowiedź
Istnieją pewne problemy z odpowiedzią udzieloną przez Dana, które mogą sprawić, że będzie to nieodpowiednie podejście w niektórych sytuacjach. Niektóre z tych problemów są wskazane w jego odpowiedzi u dołu, że jego kod da fałszywe trafienia dla elementów, które są:
clip
właściwości CSSOgraniczenia te zostały przedstawione w następujących wynikach prostego testu :
Rozwiązanie:
isElementVisible()
Oto rozwiązanie tych problemów, z poniższym wynikiem testu i objaśnieniem niektórych części kodu.
A wynik:
Dodatkowe uwagi
Ta metoda nie jest jednak pozbawiona własnych ograniczeń. Na przykład element testowany z niższym indeksem Z niż inny element w tym samym miejscu zostałby zidentyfikowany jako ukryty, nawet jeśli element z przodu faktycznie nie ukrywa żadnej jego części. Mimo to metoda ta ma zastosowanie w niektórych przypadkach, których rozwiązanie Dana nie obejmuje.
Zarówno
element.getBoundingClientRect()
idocument.elementFromPoint()
są częścią projektu specyfikacji CSSOM roboczej i są obsługiwane w co najmniej IE 6 i nowszych, a większość przeglądarek pulpitu przez długi czas (choć nie idealnie). Zobacz Quirksmode na temat tych funkcji, aby uzyskać więcej informacji.contains()
służy do sprawdzenia, czy zwracany elementdocument.elementFromPoint()
jest węzłem potomnym elementu, który testujemy pod kątem widoczności. Zwraca również wartość true, jeśli zwracany element jest tym samym elementem. Dzięki temu czek jest bardziej niezawodny. Jest obsługiwany we wszystkich głównych przeglądarkach, a Firefox 9.0 jest ostatnim z nich, aby go dodać. Aby uzyskać starszą obsługę Firefoksa, sprawdź historię tej odpowiedzi.Jeśli chcesz przetestować więcej punktów wokół elementu pod kątem widoczności ―, tj. Aby upewnić się, że element nie jest objęty więcej niż, powiedzmy, 50% ―, nie zajęłoby wiele, aby dopasować ostatnią część odpowiedzi. Pamiętaj jednak, że prawdopodobnie sprawdziłby się każdy piksel, aby upewnić się, że jest w 100% widoczny.
źródło
doc
jako aliasudocument
. Tak, lubię myśleć o tym jako o przyzwoitym rozwiązaniu w przypadku skrzynek.element.contains(efp(rect.right - (rect.width / 2), rect.bottom - (rect.height / 2)))
Próbowałem odpowiedzi Dana . Jednak algebra zastosowana do określenia granic oznacza, że element musi być zarówno ≤ wielkości rzutni, jak i całkowicie wewnątrz rzutni, aby uzyskać
true
, co łatwo prowadzi do fałszywych negatywów. Jeśli chcesz ustalić, czy element jest w ogóle w rzutni, odpowiedź Ryanve jest bliska, ale testowany element powinien nakładać się na rzutnię, więc spróbuj tego:źródło
Jako usługa publiczna:
odpowiedź Dana z poprawnymi obliczeniami (elementem może być> okno, szczególnie na ekranach telefonów komórkowych) i poprawne testowanie jQuery, a także dodanie isElementPartIALInViewport:
Nawiasem mówiąc, różnica między window.innerWidth i document.documentElement.clientWidth polega na tym, że clientWidth / clientHeight nie zawiera paska przewijania, podczas gdy window.innerWidth / Height.
Przypadek testowy
źródło
isElementPartiallyInViewport
jest również bardzo przydatny. Niezłe.Zobacz źródło verge , które korzysta z getBoundingClientRect . To jest jak:
Zwraca,
true
jeśli jakaś część elementu znajduje się w rzutni.źródło
Moja krótsza i szybsza wersja:
I jsFiddle zgodnie z wymaganiami: https://jsfiddle.net/on1g619L/1/
źródło
Niepokoiło mnie to, że nie było dostępnej dla jQuery wersji funkcjonalności. Kiedy natknąłem się na rozwiązanie Dana, zauważyłem możliwość zapewnienia czegoś dla ludzi, którzy lubią programować w stylu jQuery OO. Jest miły i zgryźliwy i działa jak urok dla mnie.
Bada bing bada boom
Stosowanie
źródło
Nowy interfejs API Intersection Observer rozwiązuje to pytanie bardzo bezpośrednio.
To rozwiązanie będzie wymagało wypełniania polifill, ponieważ Safari, Opera i Internet Explorer nie obsługują tego jeszcze (wypełnienie jest zawarte w rozwiązaniu).
W tym rozwiązaniu pole jest poza polem widzenia, które jest celem (obserwowanym). Jeśli chodzi o widok, przycisk u góry nagłówka jest ukryty. Jest pokazywany, gdy pudełko opuści widok.
źródło
<!DOCTYPE html>
do HTMLIntersectionObserver
jest to funkcja eksperymentalna (która może ulec zmianie w przyszłości).IntersectionObserver
wyzwala tylko oddzwonienie po ruchu celu względem korzenia.observe
zdarzenia natychmiast zostaje wyzwolony komunikat informujący o bieżącym stanie przecięcia śledzonego elementu. Tak więc, w jakiś sposób - dotyczy.Wszystkie odpowiedzi, które tu napotkałem, sprawdzają tylko, czy element jest umieszczony w bieżącej rzutni . Ale to nie znaczy, że jest widoczne .
Co jeśli dany element znajduje się w div z przepełnioną zawartością i jest przewijany poza pole widzenia?
Aby rozwiązać ten problem, musisz sprawdzić, czy element jest zawarty przez wszystkich rodziców.
Moje rozwiązanie robi dokładnie to:
Pozwala także określić, jak duży element ma być widoczny.
To rozwiązanie zignorowało fakt, że elementy mogą nie być widoczne z powodu innych faktów, takich jak
opacity: 0
.Przetestowałem to rozwiązanie w Chrome i Internet Explorer 11.
źródło
Uważam, że przyjęta tutaj odpowiedź jest zbyt skomplikowana w przypadku większości przypadków użycia. Ten kod dobrze wykonuje zadanie (używając jQuery) i rozróżnia elementy w pełni widoczne i częściowo widoczne:
źródło
$window = $(window)
poza modułem przewijania.Najprostsze rozwiązanie jako obsługa elementu Element.getBoundingClientRect () stało się idealne :
źródło
Myślę, że jest to bardziej funkcjonalny sposób na zrobienie tego. Odpowiedź Dana nie działa w kontekście rekurencyjnym.
Ta funkcja rozwiązuje problem, gdy element znajduje się wewnątrz innych przewijalnych div div, testując rekursywnie wszystkie poziomy aż do znacznika HTML, i zatrzymuje się przy pierwszym false.
źródło
Najczęściej akceptowane odpowiedzi nie działają podczas powiększania w Google Chrome na Androida. W połączeniu z odpowiedzią Dana , aby uwzględnić Chrome na Androida, należy użyć visualViewport . Poniższy przykład uwzględnia tylko sprawdzenie pionowe i używa jQuery dla wysokości okna:
źródło
Oto moje rozwiązanie. Działa, jeśli element jest ukryty w przewijalnym pojemniku.
Oto demo (spróbuj zmienić rozmiar okna)
Musiałem tylko sprawdzić, czy jest widoczny na osi Y (dla przewijanej funkcji ładowania więcej rekordów Ajax).
źródło
Opierając się na rozwiązaniu dana , postanowiłem wyczyścić implementację, aby korzystanie z niej wielokrotnie na tej samej stronie było łatwiejsze:
Używam go w ten sposób, że gdy element przewija się do widoku, dodaję klasę, która wyzwala animację klatki kluczowej CSS. Jest to dość proste i działa szczególnie dobrze, gdy masz ponad 10 rzeczy warunkowo animowanych na stronie.
źródło
$window = $(window)
pozaWiększość zwyczajów z poprzednich odpowiedzi kończy się niepowodzeniem w następujących punktach:
Cóż, dla wszystkich tych problemów mam rozwiązanie, a plusy to:
Jeśli sprawdzisz poniższe fragmenty, zobaczysz różnicę w użyciu
overflow-scroll
w kontenerze elementu nie spowoduje żadnych problemów i zobaczysz, że w przeciwieństwie do innych odpowiedzi tutaj, nawet jeśli piksel pojawia się z dowolnej strony lub gdy element jest większy niż obszar wyświetlania i widzimy wnętrze piksele elementu, który nadal działa.Użycie jest proste:
Demonstracja, bez
crossSearchAlgorithm
której jest przydatna dla elementów większych niż element kontrolny rzutni 3 wewnętrzne piksele, aby zobaczyć:Pokaż fragment kodu
Widzisz, gdy jesteś w elemencie3 , nie określa , czy jest widoczny, czy nie, ponieważ sprawdzamy tylko, czy element jest widoczny z boku lub z narożników .
I ta zawiera,
crossSearchAlgorithm
która pozwala ci wrócić,visible
gdy element jest większy niż rzutnia:Pokaż fragment kodu
JSFiddle do zabawy z: http://jsfiddle.net/BerkerYuceer/grk5az2c/
Ten kod ma na celu uzyskanie dokładniejszych informacji, jeśli jakaś część elementu jest pokazana w widoku, czy nie. Aby korzystać z opcji wydajności lub tylko pionowych slajdów, nie używaj tego! Ten kod jest bardziej skuteczny w rysowaniu przypadków.
źródło
Lepsze rozwiązanie:
źródło
Tak proste, jak to tylko możliwe, IMO:
źródło
Oto funkcja, która informuje, czy element jest widoczny w bieżącej rzutni elementu nadrzędnego :
źródło
Sprawdza, czy element jest przynajmniej częściowo widoczny (wymiar pionowy):
źródło
Miałem to samo pytanie i rozgryzłem je za pomocą getBoundingClientRect ().
Ten kod jest całkowicie „ogólny” i musi być napisany tylko raz, aby zadziałał (nie musisz go pisać dla każdego elementu, który chcesz wiedzieć, jest w okienku ekranu).
Ten kod sprawdza tylko, czy jest pionowo w rzutni, a nie w poziomie . W tym przypadku „elementy” zmiennej (tablicy) przechowują wszystkie elementy, które sprawdzasz, aby były pionowo w rzutni, więc chwyć dowolne elementy w dowolnym miejscu i przechowuj je tam.
„Pętla for” zapętla każdy element i sprawdza, czy znajduje się on pionowo w rzutni. Ten kod jest wykonywany za każdym razem, gdy użytkownik przewija! Jeśli getBoudingClientRect (). Top ma mniej niż 3/4 rzutni (element ma jedną czwartą w rzutni), rejestruje się jako „w rzutni”.
Ponieważ kod jest ogólny, będziesz chciał wiedzieć, który element znajduje się w rzutni. Aby się tego dowiedzieć, możesz to ustalić na podstawie niestandardowego atrybutu, nazwy węzła, identyfikatora, nazwy klasy i innych kryteriów.
Oto mój kod (powiedz mi, jeśli nie działa; został przetestowany w Internet Explorer 11, Firefox 40.0.3, Chrome Wersja 45.0.2454.85 m, Opera 31.0.1889.174 i Edge z Windows 10, [jeszcze nie Safari ]) ...
źródło
To proste i małe rozwiązanie, które zadziałało dla mnie.
Przykład : Chcesz sprawdzić, czy element jest widoczny w elemencie nadrzędnym, który ma przewijanie przepełnienia.
źródło
Wszystkie odpowiedzi tutaj określają, czy element jest całkowicie zawarty w rzutni, a nie tylko w jakiś sposób widoczny. Na przykład, jeśli tylko połowa obrazu jest widoczna u dołu widoku, rozwiązania tutaj zawiodą, biorąc pod uwagę, że „na zewnątrz”.
Miałem przypadek użycia, w którym ładuję się leniwie
IntersectionObserver
, ale z powodu animacji pojawiających się podczas wyskakującego okienka nie chciałem oglądać żadnych obrazów, które były już przecinane podczas ładowania strony. Aby to zrobić, użyłem następującego kodu:Jest to w zasadzie sprawdzenie, czy górna lub dolna granica jest niezależnie w rzutni. Przeciwny koniec może znajdować się na zewnątrz, ale dopóki jeden jest w środku, jest „widoczny” co najmniej częściowo.
źródło
Korzystam z tej funkcji (sprawdza tylko, czy y jest niewidoczne, ponieważ przez większość czasu x nie jest potrzebne)
źródło
W przypadku podobnego wyzwania bardzo podobała mi się ta treść, która ujawnia wypełnienie dla scrollIntoViewIfNeeded () .
Wszystkie niezbędne Kung Fu potrzebne do odpowiedzi znajdują się w tym bloku:
this
odnosi się do elementu, który chcesz wiedzieć, jeśli jest, na przykład,overTop
luboverBottom
- powinieneś dostać dryf ...źródło