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.)
Siehe die Quelle von Randbereich , die die getBoundingClientRect . Es ist wie:
function inViewport (element) {
if (!element) return false;
if (1 !== element.nodeType) return false;
var html = document.documentElement;
var rect = element.getBoundingClientRect();
return !!rect &&
rect.bottom >= 0 &&
rect.right >= 0 &&
rect.left <= html.clientWidth &&
rect.top <= html.clientHeight;
}
Sie gibt zurück true
wenn cualquier Teil des Elements im Ansichtsfenster liegt.
Im Dienste der Öffentlichkeit:
Dan's Antwort mit den richtigen Berechnungen (Element kann > Fenster, vor allem auf Handy-Bildschirmen), und richtige jQuery-Tests, sowie das Hinzufügen von isElementPartiallyInViewport:
Im Übrigen, der Unterschied zwischen window.i
function isElementPartiallyInViewport(el)
{
// Special bonus for those using jQuery
if (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-overlap
var 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-viewport
function isElementInViewport (el)
{
// Special bonus for those using jQuery
if (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);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Test</title>
<!--
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script src="scrollMonitor.js"></script>
-->
<script type="text/javascript">
function isElementPartiallyInViewport(el)
{
// Special bonus for those using jQuery
if (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-overlap
var 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-viewport
function isElementInViewport (el)
{
// Special bonus for those using jQuery
if (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);
}
// var scrollLeft = (window.pageXOffset !== undefined) ? window.pageXOffset : (document.documentElement || document.body.parentNode || document.body).scrollLeft,
// var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
</script>
</head>
<body>
<div style="display: block; width: 2000px; height: 10000px; background-color: green;">
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<input type="button" onclick="fnIsVis(document.getElementById('myele'));" value="det" />
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<div style="background-color: crimson; display: inline-block; width: 800px; height: 500px;" ></div>
<div id="myele" onclick="fnIsVis(this);" style="display: inline-block; width: 100px; height: 100px; background-color: hotpink;">
t
</div>
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<br /><br /><br /><br /><br /><br />
<input type="button" onclick="fnIsVis(document.getElementById('myele'));" value="det" />
</div>
<!--
<script type="text/javascript">
var element = document.getElementById("myele");
var watcher = scrollMonitor.create(element);
watcher.lock();
watcher.stateChange(function() {
console.log("state changed");
// $(element).toggleClass('fixed', this.isAboveViewport)
});
</script>
-->
</body>
</html>
For isElementInViewport(e) : Ihr Code lädt nicht einmal Bilder, Dieser ist korrekt : function 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: Keiner meiner Codes lädt Bilder, also warum sollte er, und die Formel ist korrekt.
Meine kürzere und schnellere Version:
function isElementOutViewport(el){
var rect = el.getBoundingClientRect();
return rect.bottom < 0 || rect.right < 0 || rect.left > window.innerWidth || rect.top > window.innerHeight;
}
Und ein jsFiddle nach Bedarf: https://jsfiddle.net/on1g619L/1/
Meine Lösung sind mehr gierig und schneller, wenn Element haben jedes Pixel in Viewport, es ist wird false zurückgeben.
Ich mag es. Kurz und bündig. Sie könnten die Leerzeichen zwischen Funktionsname und Klammer und zwischen Klammer und Klammer in der ersten Zeile entfernen. Ich habe diese Leerzeichen nie gemocht. Vielleicht liegt es nur an meinem Texteditor, der alles farblich kodiert, so dass es trotzdem leicht zu lesen ist. function aaa(arg){statements} Ich weiß, dass das die Ausführung nicht beschleunigt, sondern eher unter Mining fällt.
Das ist buchstäblich das Gegenteil von dem, was in der Frage gefragt wurde: Warum darf es eine solche Lösung geben? Zumindest sollte die Antwort besagen, dass diese Funktion verwendet werden kann, um zu prüfen, ob sich das Element außerhalb des Ansichtsfensters befindet, und sich nicht nur auf den Funktionsnamen verlassen, um dies zu implizieren.
Die neue Schnittpunkt Beobachter API geht auf diese Frage sehr direkt ein.
Für diese Lösung wird ein Polyfill benötigt, da Safari, Opera und Internet Explorer dies noch nicht unterstützen (das Polyfill ist in der Lösung enthalten).
Bei dieser Lösung gibt es einen Kasten außerhalb des Sichtfelds, der das Ziel (beobachtet) ist. Wenn es in den Sichtbereich kommt, ist die Schaltfläche oben in der Kopfzeile ausgeblendet. Sie wird eingeblendet, sobald der Kasten die Ansicht verlässt.
const buttonToHide = document.querySelector('button');
const hideWhenBoxInView = new IntersectionObserver((entries) => {
if (entries[0].intersectionRatio <= 0) { // If not in view
buttonToHide.style.display = "inherit";
} else {
buttonToHide.style.display = "none";
}
});
hideWhenBoxInView.observe(document.getElementById('box'));
header {
position: fixed;
top: 0;
width: 100vw;
height: 30px;
background-color: lightgreen;
}
.wrapper {
position: relative;
margin-top: 600px;
}
#box {
position: relative;
left: 175px;
width: 150px;
height: 135px;
background-color: lightblue;
border: 2px solid;
}
<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
<header>
<button>NAVIGATION BUTTON TO HIDE</button>
</header>
<div class="wrapper">
<div id="box">
</div>
</div>
Gute Umsetzung, und laut dem Link in diese Antwort es sollte Arbeit auf Safari durch Hinzufügen von <!DOCTYPE html>
zum HTML
Beachten Sie, dass IntersectionObserver
ist eine experimentelle Funktion (die sich in Zukunft ändern kann).
@KarthikChintala - es wird in allen Browsern außer IE unterstützt - und es ist auch ein Polyfill verfügbar.
Die einfachste Lösung als Unterstützung von Element.getBoundingClientRect() hat perfekt werden :
function isInView(el) {
const box = el.getBoundingClientRect();
return box.top < window.innerHeight && box.bottom >= 0;
}
Wie verhält sich das auf mobilen Browsern? Die meisten von ihnen sind fehlerhaft in Bezug auf Viewport, mit ihrer Kopfzeile gehen nach oben oder unten auf scrollen, und unterschiedliches Verhalten, wenn die Tastatur zeigt, je nachdem, ob es Android oder ios, etc.
@Kev Sollte gut funktionieren, je nachdem, wann Sie diese Methode aufrufen. Wenn du sie aufrufst und dann die Größe des Fensters änderst, könnte das Ergebnis natürlich nicht mehr korrekt sein. Sie könnten sie bei jedem Größenänderungsereignis aufrufen, je nachdem, welche Art von Funktionalität Sie wünschen. Sie können gerne eine separate Frage zu Ihrem speziellen Anwendungsfall stellen und mich hier anpingen.
In 99% der Fälle reicht das aus, vor allem, wenn man nur einen Fader oder etwas anderes starten oder stoppen muss und etwas CPU sparen will. Es sind die Entwickler, die die Geräte zu Tode orientieren, nicht die normalen Benutzer. $(window).on('scroll', function(){ if(isInView($('.fader').get(0))) {} else {} });
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