क्या यह बताने का एक कारगर तरीका है कि क्या कोई DOM तत्व (HTML डॉक्यूमेंट में) वर्तमान में दिखाई दे रहा है ( व्यूपोर्ट में दिखाई देता है )?
(सवाल फ़ायरफ़ॉक्स को संदर्भित करता है।)
क्या यह बताने का एक कारगर तरीका है कि क्या कोई DOM तत्व (HTML डॉक्यूमेंट में) वर्तमान में दिखाई दे रहा है ( व्यूपोर्ट में दिखाई देता है )?
(सवाल फ़ायरफ़ॉक्स को संदर्भित करता है।)
जवाबों:
अद्यतन: समय मार्च और इतने पर हमारे ब्राउज़र हैं। यह तकनीक अब अनुशंसित नहीं है और आपको 7 से पहले इंटरनेट एक्सप्लोरर के संस्करण का समर्थन करने की आवश्यकता नहीं है, तो आपको डैन के समाधान का उपयोग करना चाहिए ।
मूल समाधान (अब पुराना):
यह जाँच करेगा कि तत्व पूरी तरह से वर्तमान व्यूपोर्ट में दिखाई दे रहा है:
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)
);
}
यदि तत्व का कोई भी हिस्सा व्यूपोर्ट में दिखाई दे रहा है, तो आप यह निर्धारित करने के लिए इसे संशोधित कर सकते हैं:
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
);
}
getBoundingClientRect
विशेष रूप से तत्व निर्देशांक खोजने के उद्देश्य से भी बनाया है ... हम इसका उपयोग क्यों नहीं करेंगे?
अब अधिकांश ब्राउज़र getBoundingClientRect पद्धति का समर्थन करते हैं , जो सबसे अच्छा अभ्यास बन गया है। एक पुराने उत्तर का उपयोग करना बहुत धीमा है , सटीक नहीं है और इसमें कई बग हैं ।
सही के रूप में चयनित समाधान लगभग कभी सटीक नहीं होता है । आप इसके बग्स के बारे में अधिक पढ़ सकते हैं ।
यह समाधान इंटरनेट एक्सप्लोरर 7 (और बाद में), आईओएस 5 (और बाद में) सफारी, एंड्रॉइड 2.0 (एक्लेयर) और बाद में ब्लैकबेरी, ओपेरा मोबाइल और इंटरनेट एक्सप्लोरर मोबाइल 9 पर परीक्षण किया गया था ।
function isElementInViewport (el) {
// Special bonus for those using jQuery
if (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() */
);
}
आप यह सुनिश्चित कर सकते हैं कि ऊपर दिया गया फ़ंक्शन उस समय का सही उत्तर देता है जब उसे कॉल किया जाता है, लेकिन ईवेंट के रूप में ट्रैकिंग तत्व की दृश्यता के बारे में क्या?
अपने <body>
टैग के नीचे निम्नलिखित कोड रखें :
function onVisibilityChange(el, callback) {
var old_visible;
return function () {
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);
}
*/
यदि आप कोई डोम संशोधन करते हैं, तो वे आपके तत्व की दृश्यता को बदल सकते हैं।
दिशानिर्देश और सामान्य नुकसान:
हो सकता है कि आपको पृष्ठ ज़ूम / मोबाइल डिवाइस चुटकी ट्रैक करने की आवश्यकता हो? jQuery को ज़ूम / पिंच क्रॉस ब्राउज़र को संभालना चाहिए , अन्यथा पहले या दूसरे लिंक को आपकी मदद करनी चाहिए।
यदि आप DOM को संशोधित करते हैं , तो यह तत्व की दृश्यता को प्रभावित कर सकता है। आपको उस पर नियंत्रण रखना चाहिए और handler()
मैन्युअल रूप से कॉल करना चाहिए । दुर्भाग्य से, हमारे पास कोई क्रॉस ब्राउज़र onrepaint
घटना नहीं है। दूसरी ओर जो हमें अनुकूलन करने और केवल डोम संशोधनों पर फिर से जांच करने की अनुमति देता है जो किसी तत्व की दृश्यता को बदल सकते हैं।
कभी भी इसे jQuery $ (डॉक्यूमेंट) (।) ( केवल ) के अंदर उपयोग न करें , क्योंकि कोई वारंटी नहीं है CSS को इस क्षण में लागू नहीं किया गया है । आपका कोड आपके सीएसएस के साथ स्थानीय रूप से हार्ड ड्राइव पर काम कर सकता है, लेकिन एक बार रिमोट सर्वर पर डालने पर यह विफल हो जाएगा।
DOMContentLoaded
निकाल दिए जाने के बाद , शैलियों को लागू किया जाता है , लेकिन चित्र अभी तक लोड नहीं किए गए हैं । इसलिए, हमें window.onload
ईवेंट श्रोता को जोड़ना चाहिए ।
हम अभी तक ज़ूम / पिंच ईवेंट नहीं पकड़ सकते।
अंतिम उपाय निम्नलिखित कोड हो सकता है:
/* TODO: this looks like a very bad code */
setInterval(handler, 600);
यदि आप ध्यान रखते हैं कि आपके वेब पेज के साथ टैब सक्रिय और दृश्यमान है, तो आप HTML5 API की भयानक सुविधा पृष्ठ का उपयोग कर सकते हैं ।
TODO: यह विधि दो स्थितियों को नहीं संभालती है:
z-index
overflow-scroll
तत्व के कंटेनर में उपयोग करना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'))
) में पारित करने के लिए बस एक अनुकूल अनुस्मारक है और jQuery ऑब्जेक्ट (जैसे, isElementInViewport($("#elem))
) नहीं। JQuery बराबर जोड़ना है [0]
तो जैसे: isElementInViewport($("#elem)[0])
।
el is not defined
आधुनिक ब्राउज़रों में, आप इन्टर्सेशन ऑब्जर्वर एपीआई की जांच कर सकते हैं जो निम्नलिखित लाभ प्रदान करता है:
इंटरसेक्शन ऑब्जर्वर एक पूर्ण मानक होने के रास्ते पर है और पहले से ही Chrome 51+, एज 15+ और फ़ायरफ़ॉक्स 55+ में समर्थित है और सफारी के लिए विकास के अंतर्गत है। वहाँ भी एक polyfill उपलब्ध है।
दान द्वारा प्रदान किए गए उत्तर के साथ कुछ मुद्दे हैं जो इसे कुछ स्थितियों के लिए अनुपयुक्त दृष्टिकोण बना सकते हैं। इन मुद्दों में से कुछ को नीचे दिए गए उत्तर में बताया गया है, कि उनका कोड उन तत्वों के लिए झूठी सकारात्मकता देगा:
clip
संपत्ति का उपयोग करके छिपाया गयाएक साधारण परीक्षण के निम्नलिखित परिणामों में इन सीमाओं का प्रदर्शन किया जाता है :
isElementVisible()
यहां उन समस्याओं का समाधान दिया गया है, नीचे दिए गए परीक्षा परिणाम और कोड के कुछ हिस्सों की व्याख्या के साथ।
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 viewport
if (rect.right < 0 || rect.bottom < 0
|| rect.left > vWidth || rect.top > vHeight)
return false;
// Return true if any of its four corners are visible
return (
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))
);
}
पासिंग टेस्ट: http://jsfiddle.net/AndyE/cAY8c/
और परिणाम:
हालांकि, यह विधि अपनी सीमाओं के बिना नहीं है। उदाहरण के लिए, किसी तत्व को उसी स्थान पर किसी अन्य तत्व की तुलना में कम z-सूचकांक के साथ परीक्षण किया जा रहा है, भले ही सामने वाला तत्व वास्तव में उसके किसी भी हिस्से को छिपाए नहीं, भले ही छिपा हो। फिर भी, इस पद्धति के कुछ मामलों में इसके उपयोग हैं जो दान के समाधान को कवर नहीं करते हैं।
दोनों element.getBoundingClientRect()
और document.elementFromPoint()
CSSOM कार्यकारी ड्राफ्ट विनिर्देश का हिस्सा हैं और कम से कम IE 6 और बाद में में समर्थित हैं और सबसे लंबे समय के लिए डेस्कटॉप ब्राउज़र (यद्यपि, पूरी तरह से नहीं)। अधिक जानकारी के लिए इन कार्यों पर Quirksmode देखें ।
contains()
यह देखने के लिए उपयोग किया जाता है कि तत्व द्वारा लौटाया गया तत्व document.elementFromPoint()
उस बच्चे का नोड है जिसे हम दृश्यता के लिए परीक्षण कर रहे हैं। यह भी सच है अगर वापस लौटा तत्व एक ही तत्व है। यह सिर्फ चेक को अधिक मजबूत बनाता है। यह सभी प्रमुख ब्राउज़रों में समर्थित है, फ़ायरफ़ॉक्स 9.0 इसे जोड़ने के लिए उनमें से अंतिम है। पुराने फ़ायरफ़ॉक्स समर्थन के लिए, इस उत्तर के इतिहास की जाँच करें।
यदि आप दृश्यता के लिए तत्व के चारों ओर अधिक बिंदुओं का परीक्षण करना चाहते हैं, तो यह सुनिश्चित करने के लिए कि तत्व से अधिक कवर नहीं किया गया है, कहते हैं, 50% 50it उत्तर के अंतिम भाग को समायोजित करने के लिए बहुत अधिक नहीं लेगा। हालाँकि, इस बात से अवगत रहें कि यदि आप 100% दृश्यमान हैं, तो यह सुनिश्चित करने के लिए कि आपने प्रत्येक पिक्सेल की जाँच की है, तो यह बहुत धीमा होगा।
doc
एक उपनाम के रूप में उपयोग कर रहा था document
। हाँ, मैं इसे किनारे के मामलों के लिए एक सभ्य समाधान के रूप में सोचना पसंद करता हूं।
element.contains(efp(rect.right - (rect.width / 2), rect.bottom - (rect.height / 2)))
मैंने डैन के जवाब की कोशिश की । हालांकि , सीमा निर्धारित करने के लिए उपयोग किए जाने वाले बीजगणित का अर्थ है कि तत्व दोनों के व्यूपोर्ट आकार और पूरी तरह से व्यूपोर्ट के अंदर होना चाहिए true
, आसानी से झूठे नकारात्मक के लिए अग्रणी। यदि आप यह निर्धारित करना चाहते हैं कि क्या कोई तत्व व्यूपोर्ट में है, तो ryanve का उत्तर करीब है, लेकिन परीक्षण किया जा रहा तत्व व्यूपोर्ट को ओवरलैप करना चाहिए, इसलिए यह प्रयास करें:
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() */;
}
एक सार्वजनिक सेवा के रूप में:
सही गणनाओं के साथ डैन का उत्तर (तत्व हो सकता है> विंडो, विशेष रूप से मोबाइल फोन स्क्रीन पर), और सही jQuery परीक्षण, साथ ही साथ IsElementPartiallyInViewport:
वैसे, window.innerWidth और document.documentElement.clientWidth के बीच का अंतर यह है कि clientWidth / clientHeight में स्क्रॉलबार शामिल नहीं है, जबकि window.innerWidth / Height करता है।
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>
isElementPartiallyInViewport
के रूप में अच्छी तरह से बहुत उपयोगी है। अच्छा है।
का स्रोत देखें कगार , जो का उपयोग करता है getBoundingClientRect । यह पसंद है:
function inViewport (el) {
var r, html;
if ( !el || 1 !== el.nodeType ) { return false; }
html = document.documentElement;
r = el.getBoundingClientRect();
return ( !!r
&& r.bottom >= 0
&& r.right >= 0
&& r.top <= html.clientHeight
&& r.left <= html.clientWidth
);
}
true
यदि तत्व का कोई हिस्सा व्यूपोर्ट में है तो यह वापस आ जाता है।
मेरा छोटा और तेज़ संस्करण:
function isElementOutViewport(el){
var rect = el.getBoundingClientRect();
return rect.bottom < 0 || rect.right < 0 || rect.left > window.innerWidth || rect.top > window.innerHeight;
}
और आवश्यकता के अनुसार एक jsField: https://jsfiddle.net/on1g619L/1
मैंने पाया कि यह परेशान था कि कार्यक्षमता का एक jQuery -centric संस्करण उपलब्ध नहीं था। जब मैं डैन के समाधान में आया तो मैंने उन लोगों के लिए कुछ प्रदान करने का अवसर दिया जो jQuery OO शैली में प्रोग्राम करना पसंद करते हैं। यह अच्छा और डरावना है और मेरे लिए एक आकर्षण की तरह काम करता है।
बडा बिंग बडा बूम
$.fn.inView = function(){
if(!this.length)
return false;
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();
});
प्रयोग
$(window).on('scroll',function(){
if( $('footer').inView() ) {
// Do cool stuff
}
});
नया इंटर्सेक्शन ऑब्जर्वर एपीआई इस सवाल को बहुत सीधे तौर पर संबोधित करता है।
इस समाधान के लिए एक पॉलीफ़िल की आवश्यकता होगी क्योंकि सफारी, ओपेरा और इंटरनेट एक्सप्लोरर अभी तक इसका समर्थन नहीं करते हैं (पॉलीफ़िल समाधान में शामिल है)।
इस समाधान में, एक बॉक्स आउट ऑफ़ व्यू है जो लक्ष्य (मनाया गया) है। जब यह देखने में आता है, तो शीर्ष लेख में बटन छिपा होता है। एक बार बॉक्स दृश्य को छोड़ देने के बाद इसे दिखाया जाता है।
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>
<!DOCTYPE html>
IntersectionObserver
एक प्रायोगिक विशेषता है (जो भविष्य में बदल सकती है)।
IntersectionObserver
लगाने के बाद से ओपी के प्रश्न को संबोधित नहीं करता है : केवल रूट के सापेक्ष लक्ष्य की गति के बाद कॉलबैक फायर करता है।
observe
ईवेंट को तुरंत ट्रैक किए गए तत्व के वर्तमान चौराहे की स्थिति बताते हुए निकाल दिया जाता है। तो, किसी तरह से - यह संबोधित करता है।
मेरे द्वारा यहां देखे गए सभी उत्तर केवल यह देखते हैं कि तत्व वर्तमान व्यूपोर्ट के अंदर स्थित है या नहीं । लेकिन इसका मतलब यह नहीं है कि यह दिखाई दे रहा है ।
क्या होगा यदि दिया गया तत्व ओवरफ्लोइंग सामग्री के साथ एक डिव के अंदर है, और इसे देखने से बाहर स्क्रॉल किया गया है?
इसे हल करने के लिए, आपको जांचना होगा कि क्या तत्व सभी माता-पिता द्वारा निहित है।
मेरा समाधान ठीक यही करता है:
यह आपको यह निर्दिष्ट करने की भी अनुमति देता है कि तत्व को कितना दिखाई देना है।
Element.prototype.isVisible = function(percentX, percentY){
var tolerance = 0.01; //needed because the rects returned by getBoundingClientRect provide the position up to 10 decimals
if(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;
};
इस समाधान ने इस तथ्य को नजरअंदाज कर दिया कि तत्व अन्य तथ्यों के कारण दिखाई नहीं दे सकते हैं, जैसे opacity: 0
।
मैंने क्रोम और इंटरनेट एक्सप्लोरर 11 में इस समाधान का परीक्षण किया है।
मुझे लगता है कि ज्यादातर उपयोग के मामलों के लिए यहां स्वीकृत उत्तर अत्यधिक जटिल है। यह कोड अच्छी तरह से काम करता है (jQuery का उपयोग करके) और पूरी तरह से दृश्यमान और आंशिक रूप से दृश्य तत्वों के बीच अंतर करता है:
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)");
} else if (windowScrollTop > bottomOfElement && windowScrollTop > topOfElement) {
// Element is hidden (above viewable area)
console.log("Element is hidden (above viewable area)");
} else if (scrollTopPosition < topOfElement && scrollTopPosition < bottomOfElement) {
// Element is hidden (below viewable area)
console.log("Element is hidden (below viewable area)");
} else if (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");
}
});
$window = $(window)
स्क्रॉल हैंडलर के बाहर निश्चित रूप से कैश होना चाहिए ।
सरल समाधान के समर्थन के रूप में Element.getBoundingClientRect () है आदर्श बन :
function isInView(el) {
let box = el.getBoundingClientRect();
return box.top < window.innerHeight && box.bottom >= 0;
}
मुझे लगता है कि यह करने का एक अधिक कार्यात्मक तरीका है। दान का जवाब एक पुनरावर्ती संदर्भ में काम नहीं करता है।
यह फ़ंक्शन उस समस्या को हल करता है जब आपका तत्व किसी स्क्रॉलिंग डिव के अंदर होता है, जो HTML टैग के लिए पुनरावर्ती स्तर तक किसी भी स्तर का परीक्षण करता है, और पहले गलत पर रुकता है।
/**
* fullVisible=true only returns true if the all object rect is visible
*/
function isReallyVisible(el, fullVisible) {
if ( el.tagName == "HTML" )
return true;
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)
);
};
Android पर Google Chrome में ज़ूम करते समय सबसे स्वीकृत उत्तर काम नहीं करते हैं। Android पर Chrome के लिए खाते में Dan के उत्तर के साथ संयोजन में , VisualViewport का उपयोग किया जाना चाहिए। निम्न उदाहरण केवल ऊर्ध्वाधर जांच को ध्यान में रखता है और खिड़की की ऊंचाई के लिए jQuery का उपयोग करता है:
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);
यहाँ मेरा समाधान है। यह काम करेगा यदि कोई तत्व स्क्रॉल करने योग्य कंटेनर के अंदर छिपा हुआ है।
यहाँ एक डेमो है (विंडो को फिर से आकार देने की कोशिश करें)
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;
};
मुझे केवल यह देखने की ज़रूरत है कि यह वाई अक्ष में दिखाई दे रहा है (स्क्रॉलिंग अजाक्स लोड-अधिक-रिकॉर्ड सुविधा के लिए)।
डैन के समाधान के आधार पर , मुझे कार्यान्वयन को साफ करने पर जाना था ताकि एक ही पृष्ठ पर कई बार इसका उपयोग करना आसान हो:
$(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()
);
}
});
जिस तरह से मैं इसका उपयोग कर रहा हूं वह यह है कि जब तत्व स्क्रॉल करता है, तो मैं एक वर्ग जोड़ रहा हूं जो सीएसएस कीफ़्रेम एनीमेशन को ट्रिगर करता है। यह बहुत सीधा है और विशेष रूप से अच्छी तरह से काम करता है जब आप एक पृष्ठ पर सशर्त रूप से चेतन करने के लिए 10+ चीजों की तरह हो गए हैं।
$window = $(window)
स्क्रॉल हैंडलर के बाहर कैश करना चाहिए
पिछले उत्तरों में अधिकांश usages इन बिंदुओं पर विफल हो रहे हैं:
-जब किसी तत्व का कोई पिक्सेल दिखाई देता है, लेकिन " एक कोना " नहीं:
-जब कोई तत्व व्यूपोर्ट से बड़ा और केंद्रित हो ,
उनमें से ज्यादातर केवल एक दस्तावेज़ या खिड़की के अंदर एक विलक्षण तत्व के लिए जाँच कर रहे हैं ।
खैर, इन सभी समस्याओं के लिए मेरे पास एक समाधान है और प्लस साइड हैं:
-आप
visible
तभी लौट सकते हैं जब किसी भी तरफ से केवल एक पिक्सेल ही दिखाई दे और वह एक कोने का न हो,-आप अभी भी वापस जा सकते हैं
visible
जब तत्व viewport से बड़ा है,-आप अपना चयन कर सकते हैं
parent element
या आप स्वचालित रूप से इसे चुनने दे सकते हैं,गतिशील रूप से जोड़े गए तत्वों पर भी काम करता है।
यदि आप नीचे दिए गए स्निपेट की जांच करते हैं, तो आपको overflow-scroll
तत्व के कंटेनर में उपयोग करने में अंतर दिखाई देगा, इससे कोई परेशानी नहीं होगी और देखेंगे कि अन्य उत्तरों के विपरीत यहां तक कि अगर कोई पिक्सेल किसी भी तरफ से दिखाता है या जब कोई तत्व व्यूपोर्ट से बड़ा है और हम भीतर देख रहे हैं तत्व का पिक्सेल यह अभी भी काम करता है।
उपयोग सरल है:
// 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
वह प्रदर्शन crossSearchAlgorithm
जिसके बिना व्यूपोर्ट चेक एलिमेंट 3 इनर पिक्सल से बड़े तत्वों के लिए उपयोगी है, जिसे देखने के लिए:
आप देखते हैं, जब आप एलिमेंट 3 के अंदर होते हैं, तो यह बताने में विफल रहता है कि यह दिखाई दे रहा है या नहीं, क्योंकि हम केवल जाँच कर रहे हैं कि एलीमेंट पक्षों या कोनों से दिखाई दे रहा है या नहीं ।
और इसमें वह शामिल है crossSearchAlgorithm
जो आपको visible
तब भी वापस आने की अनुमति देता है जब तत्व व्यूपोर्ट से बड़ा हो:
JSFiddle इसके साथ खेलने के लिए: http://jsfiddle.net/BerkerYuceer/grk5az2c/
यह कोड अधिक सटीक जानकारी के लिए बनाया गया है यदि तत्व का कोई हिस्सा दृश्य में दिखाया गया है या नहीं। प्रदर्शन विकल्प या केवल ऊर्ध्वाधर स्लाइड के लिए, इसका उपयोग न करें! यह कोड ड्राइंग मामलों में अधिक प्रभावी है।
एक बेहतर समाधान:
function getViewportSize(w) {
var w = w || window;
if(w.innerWidth != null)
return {w:w.innerWidth, h:w.innerHeight};
var d = w.document;
if (document.compatMode == "CSS1Compat") {
return {
w: d.documentElement.clientWidth,
h: d.documentElement.clientHeight
};
}
return { w: d.body.clientWidth, h: d.body.clientWidth };
}
function isViewportVisible(e) {
var box = e.getBoundingClientRect();
var height = box.height || (box.bottom - box.top);
var width = box.width || (box.right - box.left);
var viewport = getViewportSize();
if(!height || !width)
return false;
if(box.top > viewport.h || box.bottom < 0)
return false;
if(box.right < 0 || box.left > viewport.w)
return false;
return true;
}
यहां एक फ़ंक्शन है जो बताता है कि क्या कोई तत्व मूल तत्व के वर्तमान व्यूपोर्ट में दिखाई देता है :
function inParentViewport(el, pa) {
if (typeof jQuery === "function"){
if (el instanceof jQuery)
el = el[0];
if (pa instanceof jQuery)
pa = pa[0];
}
var e = el.getBoundingClientRect();
var p = pa.getBoundingClientRect();
return (
e.bottom >= p.top &&
e.right >= p.left &&
e.top <= p.bottom &&
e.left <= p.right
);
}
यह जांचता है कि क्या तत्व कम से कम आंशिक रूप से देखने में है (ऊर्ध्वाधर आयाम):
function inView(element) {
var box = element.getBoundingClientRect();
return inViewBox(box);
}
function inViewBox(box) {
return ((box.bottom < 0) || (box.top > getWindowSize().h)) ? false : true;
}
function getWindowSize() {
return { w: document.body.offsetWidth || document.documentElement.offsetWidth || window.innerWidth, h: document.body.offsetHeight || document.documentElement.offsetHeight || window.innerHeight}
}
मैं एक ही सवाल था और getBoundingClientRect () का उपयोग करके यह पता लगाया।
यह कोड पूरी तरह से 'जेनेरिक' है और इसे काम करने के लिए केवल एक बार लिखा जाना है (आपको इसे उस प्रत्येक तत्व के लिए नहीं लिखना है जिसे आप जानना चाहते हैं कि आप व्यूपोर्ट में हैं)।
यह कोड केवल यह देखने के लिए जांचता है कि यह व्यूपोर्ट में लंबवत है, क्षैतिज रूप से नहीं । इस स्थिति में, चर (सरणी) 'तत्व' उन सभी तत्वों को रखता है जिन्हें आप व्यूपोर्ट में लंबवत होने के लिए जाँच रहे हैं, इसलिए किसी भी तत्व को आप कहीं भी पकड़ सकते हैं और उन्हें वहां संग्रहीत कर सकते हैं।
'लूप के लिए', प्रत्येक तत्व के माध्यम से लूप करता है और यह देखने के लिए चेक करता है कि यह व्यूपोर्ट में लंबवत है या नहीं। उपयोगकर्ता द्वारा स्क्रॉल किए जाने पर यह कोड हर बार निष्पादित होता है ! यदि getBoudingClientRect ()। शीर्ष 3/4 से कम है (व्यूपोर्ट में तत्व एक चौथाई है), तो यह 'व्यूपोर्ट में' के रूप में पंजीकृत है।
चूंकि कोड सामान्य है, आप यह जानना चाहेंगे कि व्यूपोर्ट में कौन सा तत्व है। यह पता लगाने के लिए, आप इसे कस्टम विशेषता, नोड नाम, आईडी, वर्ग नाम और बहुत कुछ द्वारा निर्धारित कर सकते हैं।
यहां मेरा कोड है (मुझे बताएं कि क्या यह काम नहीं करता है? यह इंटरनेट एक्सप्लोरर 11, फ़ायरफ़ॉक्स 40.0.3, क्रोम संस्करण 45.0.2454.85 मीटर, ओपेरा 31.0.1889.174 और विंडोज 10 के साथ एज में परीक्षण किया गया है, [सफारी अभी तक नहीं ]) ...
// 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.');
}
};
यह आसान और छोटा उपाय है जो मेरे लिए काम कर रहा है।
उदाहरण : आप देखना चाहते हैं कि तत्व मूल तत्व में दिखाई देता है जिसमें ओवरफ्लो स्क्रॉल है।
$(window).on('scroll', function () {
var container = $('#sidebar');
var containerHeight = container.height();
var scrollPosition = $('#row1').offset().top - container.offset().top;
if (containerHeight < scrollPosition) {
console.log('not visible');
} else {
console.log('visible');
}
})
यहां सभी उत्तर निर्धारित कर रहे हैं कि तत्व पूरी तरह से व्यूपोर्ट में निहित है, न कि किसी तरह से दिखाई दे रहा है। उदाहरण के लिए, यदि दृश्य के तल पर केवल एक छवि दिखाई देती है, तो यहां समाधान "" बाहर "" मानते हुए विफल हो जाएंगे।
मेरे पास एक उपयोग का मामला था जहां मैं आलसी लोडिंग कर रहा हूं IntersectionObserver
, लेकिन पॉप-इन के दौरान होने वाले एनिमेशन के कारण, मैं किसी भी चित्र का निरीक्षण नहीं करना चाहता था जो पहले से ही पेज लोड पर इंटरसेक्ट किए गए थे । ऐसा करने के लिए, मैंने निम्नलिखित कोड का उपयोग किया:
const bounding = el.getBoundingClientRect();
const isVisible = (0 < bounding.top && bounding.top < (window.innerHeight || document.documentElement.clientHeight)) ||
(0 < bounding.bottom && bounding.bottom < (window.innerHeight || document.documentElement.clientHeight));
यह मूल रूप से देखने के लिए जाँच कर रहा है कि या तो ऊपर या नीचे की सीमा स्वतंत्र रूप से व्यूपोर्ट में है या नहीं। विपरीत छोर बाहर हो सकता है, लेकिन जब तक एक छोर अंदर है, यह कम से कम आंशिक रूप से "दृश्यमान" है।
मैं इस फ़ंक्शन का उपयोग करता हूं (यह केवल तभी जांचता है कि जब x की आवश्यकता नहीं है, तो अधिकांश समय से y inscreen है)
function elementInViewport(el) {
var elinfo = {
"top":el.offsetTop,
"height":el.offsetHeight,
};
if (elinfo.top + elinfo.height < window.pageYOffset || elinfo.top > window.pageYOffset + window.innerHeight) {
return false;
} else {
return true;
}
}
इसी तरह की चुनौती के लिए, मैंने वास्तव में इस जिस्ट का आनंद लिया, जो स्क्रॉल इनटू व्यूआईफाइनेड () के लिए पॉलीफिल को उजागर करता है ।
उत्तर देने के लिए आवश्यक सभी कुंग फू इस ब्लॉक के भीतर हैं:
var parent = this.parentNode,
parentComputedStyle = window.getComputedStyle(parent, null),
parentBorderTopWidth = parseInt(parentComputedStyle.getPropertyValue('border-top-width')),
parentBorderLeftWidth = parseInt(parentComputedStyle.getPropertyValue('border-left-width')),
overTop = this.offsetTop - parent.offsetTop < parent.scrollTop,
overBottom = (this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth) > (parent.scrollTop + parent.clientHeight),
overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft,
overRight = (this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth) > (parent.scrollLeft + parent.clientWidth),
alignWithTop = overTop && !overBottom;
this
उस तत्व को संदर्भित करता है जिसे आप जानना चाहते हैं कि क्या यह है, उदाहरण के लिए, overTop
या overBottom
- आपको बस बहाव मिलना चाहिए ...