Gibt es eine effiziente Methode, um festzustellen, ob ein DOM-Element (in einem HTML-Dokument) derzeit sichtbar ist (erscheint in der Ansichtsfenster )?
(Die Frage bezieht sich auf Firefox.)
Gibt es eine effiziente Methode, um festzustellen, ob ein DOM-Element (in einem HTML-Dokument) derzeit sichtbar ist (erscheint in der Ansichtsfenster )?
(Die Frage bezieht sich auf Firefox.)
Hier ist meine Lösung. Es wird funktionieren, wenn ein Element innerhalb eines scrollbaren Containers ausgeblendet wird.
Hier ist eine Demo (versuchen Sie, die Größe des Fensters zu ändern)
var visibleY = function(el){
var top = el.getBoundingClientRect().top, rect, el = el.parentNode;
do {
rect = el.getBoundingClientRect();
if (top <= rect.bottom === false)
return false;
el = el.parentNode;
} while (el != document.body);
// Check it's within the document viewport
return top <= document.documentElement.clientHeight;
};
Ich musste nur prüfen, ob er auf der Y-Achse sichtbar ist (für eine Ajax-Funktion zum Laden weiterer Datensätze mit Bildlauf).
Die meisten akzeptierten Antworten funktionieren nicht beim Zoomen in Google Chrome auf Android. In Kombination mit Dans Antwort , um Chrome auf Android zu berücksichtigen, visualViewport verwendet werden muss. Das folgende Beispiel berücksichtigt nur die vertikale Prüfung und verwendet jQuery für die Fensterhöhe:
var Rect = YOUR_ELEMENT.getBoundingClientRect();
var ElTop = Rect.top, ElBottom = Rect.bottom;
var WindowHeight = $(window).height();
if(window.visualViewport) {
ElTop -= window.visualViewport.offsetTop;
ElBottom -= window.visualViewport.offsetTop;
WindowHeight = window.visualViewport.height;
}
var WithinScreen = (ElTop >= 0 && ElBottom <= WindowHeight);
Basierend auf Dans Lösung Ich habe versucht, die Implementierung zu bereinigen, damit es einfacher ist, sie mehrmals auf derselben Seite zu verwenden:
$(function() {
$(window).on('load resize scroll', function() {
addClassToElementInViewport($('.bug-icon'), 'animate-bug-icon');
addClassToElementInViewport($('.another-thing'), 'animate-thing');
// repeat as needed ...
});
function addClassToElementInViewport(element, newClass) {
if (inViewport(element)) {
element.addClass(newClass);
}
}
function inViewport(element) {
if (typeof jQuery === "function" && element instanceof jQuery) {
element = element[0];
}
var elementBounds = element.getBoundingClientRect();
return (
elementBounds.top >= 0 &&
elementBounds.left >= 0 &&
elementBounds.bottom <= $(window).height() &&
elementBounds.right <= $(window).width()
);
}
});
Die Art, wie ich es verwende ist, dass, wenn das Element in die Ansicht scrollt, ich bin eine Klasse hinzufügen, die eine CSS-Keyframe-Animation auslöst. Es ist ziemlich geradlinig und funktioniert besonders gut, wenn Sie wie 10+ Dinge auf einer Seite bedingt animieren haben.
Die meisten der in den vorherigen Antworten genannten Verwendungen scheitern an diesen Punkten:
-Wenn ein beliebiges Pixel eines Elements sichtbar ist, aber nicht " eine Ecke ",
-Wenn ein Element größer als das Ansichtsfenster und zentriert ,
-Die meisten von ihnen prüfen nur ein einzelnes Element innerhalb eines Dokuments oder Fensters .
Nun, für all diese Probleme habe ich eine Lösung, und das sind die Vorteile:
-Sie können zurückkehren
visible
wenn nur ein Pixel von irgendeiner Seite auftaucht und keine Ecke ist,-Sie können noch zurückkehren
visible
wenn das Element größer als das Ansichtsfenster ist,-Sie können Ihr
parent element
oder Sie können es automatisch auswählen lassen,-Arbeiten an dynamisch hinzugefügte Elemente auch.
Anhand der nachstehenden Ausschnitte können Sie den Unterschied bei der Verwendung von overflow-scroll
im Container des Elements wird keine Probleme verursachen und dafür sorgen, dass im Gegensatz zu anderen Antworten hier auch wenn ein Pixel aus beliebige Seite oder wenn ein Element größer ist als der Viewport und wir sehen innere Pixel des Elements es funktioniert immer noch.
Die Verwendung ist einfach:
// For checking element visibility from any sides
isVisible(element)
// For checking elements visibility in a parent you would like to check
var 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
Eine Demonstration ohne crossSearchAlgorithm
was für Elemente nützlich ist, die größer sind als der Viewport, überprüfen Sie die inneren Pixel von element3:
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 viewport
if (rect.right < prect.left || rect.bottom < prect.top || rect.left > prect.right || rect.top > prect.bottom) {
return false;
}
var flag = false;
// Return true if left to right any border pixel reached
for (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 reached
if (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 viewport
if (flag == false) {
var x = rect.left;
var y = rect.top;
// From top left to bottom right
while(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 left
while(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
if (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 elements
for(var i=4; i <= 6; i++) {
var newElement = document.createElement("div");
newElement.id = "element" + i;
newElement.classList.add("element");
document.getElementById('container').appendChild(newElement);
}
#console { background-color: yellow; }
#container {
width: 300px;
height: 100px;
background-color: lightblue;
overflow-y: auto;
padding-top: 150px;
margin: 45px;
}
.element {
margin: 400px;
width: 400px;
height: 320px;
background-color: green;
}
#element3 {
position: relative;
margin: 40px;
width: 720px;
height: 520px;
background-color: green;
}
#element3::before {
content: "";
position: absolute;
top: -10px;
left: -10px;
margin: 0px;
width: 740px;
height: 540px;
border: 5px dotted green;
background: transparent;
}
<div id="console"></div>
<div id="container">
<div id="element1" class="element"></div>
<div id="element2" class="element"></div>
<div id="element3" class="element"></div>
</div>
Sie sehen, wenn Sie innerhalb des Elements3 kann nicht festgestellt werden, ob es sichtbar ist oder nicht, da wir nur prüfen, ob das Element von Seiten o Ecken .
Und diese beinhaltet crossSearchAlgorithm
die es Ihnen ermöglicht, weiterhin visible
wenn das Element größer als das Ansichtsfenster ist:
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 viewport
if (rect.right < prect.left || rect.bottom < prect.top || rect.left > prect.right || rect.top > prect.bottom) {
return false;
}
var flag = false;
// Return true if left to right any border pixel reached
for (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 reached
if (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 viewport
if (flag == false) {
var x = rect.left;
var y = rect.top;
// From top left to bottom right
while(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 left
while(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 crossSearchAlgorithm
if (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 elements
for(var i=4; i <= 6; i++) {
var newElement = document.createElement("div");
newElement.id = "element" + i;
newElement.classList.add("element");
document.getElementById('container').appendChild(newElement);
}
#console { background-color: yellow; }
#container {
width: 300px;
height: 100px;
background-color: lightblue;
overflow-y: auto;
padding-top: 150px;
margin: 45px;
}
.element {
margin: 400px;
width: 400px;
height: 320px;
background-color: green;
}
#element3 {
position: relative;
margin: 40px;
width: 720px;
height: 520px;
background-color: green;
}
#element3::before {
content: "";
position: absolute;
top: -10px;
left: -10px;
margin: 0px;
width: 740px;
height: 540px;
border: 5px dotted green;
background: transparent;
}
<div id="console"></div>
<div id="container">
<div id="element1" class="element"></div>
<div id="element2" class="element"></div>
<div id="element3" class="element"></div>
</div>
JSFiddle zum Mitspielen: http://jsfiddle.net/BerkerYuceer/grk5az2c/
Dieser Code ist für genauere Informationen darüber gedacht, ob ein Teil des Elements in der Ansicht angezeigt wird oder nicht. Für Leistungsoptionen oder nur vertikale Dias sollten Sie diesen Code nicht verwenden! Dieser Code ist in Zeichnungsfällen effektiver.
Ich hatte die gleiche Frage und fand es heraus, indem ich getBoundingClientRect() verwendete.
Dieser Code ist völlig "generisch" und muss nur einmal geschrieben werden, damit er funktioniert (Sie müssen ihn nicht für jedes Element schreiben, von dem Sie wissen wollen, dass es sich im Ansichtsfenster befindet).
Dieser Code prüft nur, ob er sich vertikal im Ansichtsfenster befindet, nicht waagerecht . In diesem Fall enthält die Variable (Array) "elements" alle Elemente, bei denen Sie prüfen, ob sie sich vertikal im Ansichtsfenster befinden, also greifen Sie sich beliebige Elemente, die Sie irgendwo haben wollen, und speichern Sie sie dort.
Die "for-Schleife" durchläuft jedes Element und prüft, ob es sich vertikal im Ansichtsfenster befindet. Dieser Code führt aus jedes Mal der Benutzer scrollt! Wenn getBoudingClientRect().top weniger als 3/4 des Viewports beträgt (das Element befindet sich zu einem Viertel im Viewport), wird es als "im Viewport" registriert.
Da der Code generisch ist, müssen Sie wissen, welches Element sich im Ansichtsfenster befindet. Um das herauszufinden, können Sie es über ein benutzerdefiniertes Attribut, den Knotennamen, die ID, den Klassennamen und mehr bestimmen.
Hier ist mein Code (sagen Sie mir, wenn er nicht funktioniert; er wurde in Internet Explorer 11, Firefox 40.0.3, Chrome Version 45.0.2454.85 m, Opera 31.0.1889.174 und Edge mit Windows 10 getestet, [noch nicht 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.');
}
};
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
1 Stimmen
Es kommt darauf an, was Sie unter sichtbar verstehen. Wenn Sie meinen, dass es derzeit auf der Seite angezeigt wird, können Sie es anhand des y-Offsets des Elements und der aktuellen Bildlaufposition berechnen.
1 Stimmen
Ich habe hinzugefügt meine eigene Lösung die dieses Problem löst
1 Stimmen
Berücksichtigt eine dieser Lösungen den Z-Index eines Dom-Knotens und wie das die Sichtbarkeit speziell durch möglicherweise Ausblenden von Elementen mit einem niedrigeren Z-Index beeinflussen könnte?
1 Stimmen
Keine der angebotenen Antworten funktioniert mit absolut positionierten Elementen.
1 Stimmen
Eine Antwort für 2019: IntersectionObserver
3 Stimmen
Es gibt eine Million Antworten und die meisten sind lächerlich lang. Siehe hier für einen Zweizeiler
0 Stimmen
Verwenden Sie die Schnittpunkt-Beobachter-API, um zu erkennen, ob sich ein Element im Ansichtsfenster befindet, Details hier - frontendguruji.com/blog/
0 Stimmen
Zusätzlich zu den Antworten auf die Fragen von Intersection Observer eignet sich dieser Visualizer hervorragend für die Konfiguration der Variablen für Intersection Observer: codepen.io/michellebarker/pen/xxwLpRG