কোনও ডিওএম উপাদান (এইচটিএমএল ডকুমেন্টে) বর্তমানে দৃশ্যমান ( ভিউপোর্টে প্রদর্শিত হবে) তা বলার কোনও কার্যকর উপায় আছে কি ?
(প্রশ্নটি ফায়ারফক্সকে বোঝায়))
কোনও ডিওএম উপাদান (এইচটিএমএল ডকুমেন্টে) বর্তমানে দৃশ্যমান ( ভিউপোর্টে প্রদর্শিত হবে) তা বলার কোনও কার্যকর উপায় আছে কি ?
(প্রশ্নটি ফায়ারফক্সকে বোঝায়))
উত্তর:
আপডেট: সময় মার্চ করে এবং তাই আমাদের ব্রাউজারগুলি। এই কৌশলটি আর সুপারিশ করা হয়নি এবং আপনার যদি 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 জুম / চিম্টি ক্রস ব্রাউজার হ্যান্ডেল করা উচিত , অন্যথায় প্রথম বা দ্বিতীয় লিঙ্কটি আপনাকে সহায়তা করা উচিত।
আপনি যদি ডিওএম সংশোধন করেন তবে এটি উপাদানটির দৃশ্যমানতাকে প্রভাবিত করতে পারে। আপনার এটি নিয়ন্ত্রণ করা উচিত এবং handler()
ম্যানুয়ালি কল করা উচিত। দুর্ভাগ্যক্রমে, আমাদের কোনও ক্রস ব্রাউজার নেইonrepaint
ইভেন্ট নেই। অন্যদিকে যা আমাদের অনুকূলতা তৈরি করতে এবং কেবলমাত্র ডিওএম পরিবর্তনগুলিতে পুনরায় চেক করার অনুমতি দেয় যা কোনও উপাদানের দৃশ্যমানতা পরিবর্তন করতে পারে।
এটি কখনই jQuery inside (ডকুমেন্ট) এর অভ্যন্তরে ব্যবহার করবেন না only কেবলমাত্র প্রস্তুত () , কারণ কোনও ওয়ারেন্টি নেই সিএসএস প্রয়োগ করা হয়েছে এই মুহূর্তে। আপনার কোডটি একটি হার্ড ড্রাইভে আপনার সিএসএসের সাথে স্থানীয়ভাবে কাজ করতে পারে তবে একবার দূরবর্তী সার্ভারে রাখলে এটি ব্যর্থ হবে।
DOMContentLoaded
বরখাস্ত করার পরে , শৈলী প্রয়োগ করা হয় , তবে চিত্রগুলি এখনও লোড হয়নি । সুতরাং, আমাদের window.onload
ইভেন্ট শ্রোতা যুক্ত করা উচিত ।
আমরা এখনও জুম / পিঞ্চ ইভেন্টটি ধরতে পারি না।
শেষ অবলম্বন নিম্নলিখিত কোড হতে পারে:
/* TODO: this looks like a very bad code */
setInterval(handler, 600);
আপনি দুর্দান্ত বৈশিষ্ট্য পৃষ্ঠাটি ব্যবহার করতে পারেন ভিসিবিলি যদি আপনার ওয়েব পৃষ্ঠার সাথে থাকা ট্যাবটি সক্রিয় এবং দৃশ্যমান হয় তবে যত্নশীল যদি আপনি HTML5 API এর ।
টোডো: এই পদ্ধতিটি দুটি পরিস্থিতিতে পরিচালনা করে না:
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
আধুনিক ব্রাউজারগুলিতে, আপনি অন্তর্ভুক্তি পর্যবেক্ষক API টি যাচাই করতে চান যা নীচের সুবিধাগুলি সরবরাহ করে:
ছেদটি পর্যবেক্ষক পুরোপুরি মানসম্পন্ন হওয়ার পথে এবং ইতোমধ্যে ক্রোম 51+, এজ 15+ এবং ফায়ারফক্স 55+ এ সমর্থিত এবং সাফারিটির জন্য বিকাশাধীন। একটি পলিফিলও পাওয়া যায়।
ড্যানের দেওয়া উত্তরের সাথে কিছু সমস্যা রয়েছে যা এটি কিছু পরিস্থিতিতে অনুপযুক্ত দৃষ্টিভঙ্গি তৈরি করতে পারে। এর কয়েকটি নীচের দিকে তার উত্তরে উল্লেখ করা হয়েছে যে তার কোডটি এমন উপাদানগুলির জন্য মিথ্যা ইতিবাচক প্রতিক্রিয়া দেবে:
clip
সম্পত্তি ব্যবহার করে একটি উপাদান বা তার শিশুদের লুকানোএই সীমাবদ্ধতাগুলি একটি সাধারণ পরীক্ষার নিম্নলিখিত ফলাফলগুলিতে প্রদর্শিত হয় :
isElementVisible()
নীচে পরীক্ষার ফলাফল এবং কোডের কিছু অংশের ব্যাখ্যা সহ সেই সমস্যাগুলির সমাধান এখানে Here
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/
এবং ফলাফল:
এই পদ্ধতিটি অবশ্য নিজস্ব সীমাবদ্ধতা ছাড়াই নয়। উদাহরণস্বরূপ, একই স্থানে থাকা অন্য উপাদানের তুলনায় নিম্ন জেড-ইনডেক্সের সাথে পরীক্ষিত কোনও উপাদানটি গোপন হিসাবে চিহ্নিত হবে এমনকি সামনের উপাদানটি এর কোনও অংশ লুকায় না। তবুও, ড্যানের সমাধানটি কভার করে না এমন কিছু ক্ষেত্রে এই পদ্ধতির ব্যবহার রয়েছে।
উভয়ই element.getBoundingClientRect()
এবং document.elementFromPoint()
সিএসএসওএম ওয়ার্কিং ড্রাফ্ট স্পেসিফিকেশনের অংশ এবং কমপক্ষে IE 6 এবং তারপরে এবং বেশিরভাগ ডেস্কটপ ব্রাউজারগুলিতে দীর্ঘ সময়ের জন্য সমর্থিত (তবে পুরোপুরি নয়)। এই ফাংশনগুলির উপর Quirksmode দেখুনআরও তথ্যের জন্য ।
contains()
যে উপাদানটি ফেরত দিয়েছিল document.elementFromPoint()
তা হ'ল উপাদানটির চাইল্ড নোড, যা আমরা দৃশ্যমানতার জন্য পরীক্ষা করছি to ফিরে আসা উপাদানটি একই উপাদান হলে এটি সত্যও ফিরে আসে। এটি চেকটিকে আরও শক্তিশালী করে তোলে। এটি সমস্ত বড় ব্রাউজারগুলিতে সমর্থিত, ফায়ারফক্স 9.0 এটিকে যুক্ত করা তাদের মধ্যে শেষ। পুরানো ফায়ারফক্স সমর্থনের জন্য, এই উত্তরের ইতিহাস পরীক্ষা করুন।
আপনি যদি দৃশ্যমানতার জন্য উপাদানটির চারপাশে আরও বেশি পয়েন্ট পরীক্ষা করতে চান - যেমন, উপাদানটি এর চেয়ে বেশি আচ্ছাদিত না হয়েছে তা নিশ্চিত করার জন্য, বলুন, 50% - উত্তরের শেষ অংশটি সামঞ্জস্য করতে খুব বেশি লাগবে না। তবে, সচেতন হন যে আপনি যদি 100 পিক্সেলটি দৃশ্যমান তা নিশ্চিত করার জন্য প্রতিটি পিক্সেলটি পরীক্ষা করেন তবে এটি সম্ভবত খুব ধীর হবে।
doc
একটি উপন্যাস হিসাবে ব্যবহার করছি document
। হ্যাঁ, আমি এটিকে প্রান্তের ক্ষেত্রে একটি শালীন সমাধান হিসাবে ভাবতে চাই।
element.contains(efp(rect.right - (rect.width / 2), rect.bottom - (rect.height / 2)))
আমি ড্যান এর উত্তর চেষ্টা করেছিলাম । তবে সীমা নির্ধারণ করতে ব্যবহৃত বীজগণিতের অর্থ হল যে উপাদানটি উভয়ই হওয়া উচিত get ভিউপোর্টের আকার এবং সম্পূর্ণরূপে ভিউপোর্টের অভ্যন্তরে থাকা true
, সহজেই মিথ্যা নেতিবাচক দিকে পরিচালিত করে। যদি আপনি নির্ধারণ করতে চান যে কোনও উপাদান আদৌ ভিউপোর্টে রয়েছে কিনা, রাইভের উত্তরটি নিকটে, তবে যে উপাদানটির পরীক্ষা করা হচ্ছে তা ভিউপোর্টকে ওভারল্যাপ করা উচিত, তাই এটি চেষ্টা করুন:
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() */;
}
পাবলিক সার্ভিস হিসাবে:
সঠিক গণনার সাথে ড্যানের উত্তর (উপাদানটি> উইন্ডো হতে পারে, বিশেষত মোবাইল ফোনের স্ক্রিনে) এবং সঠিক জিকুয়েরি পরীক্ষার পাশাপাশি ইলেক্ট পার্টিশনালইন ভিউপোর্টটি যুক্ত করে:
উপায় দ্বারা, পার্থক্য window.innerWidth এবং document.documentElement.clientWidth মধ্যে যে clientWidth / clientHeight, স্ক্রলবার অন্তর্ভুক্ত নয় যখন window.innerWidth / উচ্চতা নেই।
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;
}
এবং প্রয়োজন মতো একটি জেএসফিডাল: https://jsfiddle.net/on1g619L/1/
আমি এটা কষ্ট যে একটি ছিল না পাওয়া jQuery এর কার্যকারিতা উপলব্ধ -centric সংস্করণ। আমি যখন ড্যানের সমাধানটি পেলাম পেলাম ভাবীদের জন্য কিছু সরবরাহ করার সুযোগটি দেখেছি যারা jQuery ওও স্টাইলে প্রোগ্রাম করতে পছন্দ করে। এটি সুন্দর এবং চটজলদি এবং আমার জন্য কবজির মতো কাজ করে।
বাড়া বিং বাদা বুম
$.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
}
});
নতুন ছেদটি পর্যবেক্ষক এপিআই এই প্রশ্নটিকে খুব সরাসরি সম্বোধন করে।
এই সমাধানটির একটি পলিফিলের প্রয়োজন হবে কারণ সাফারি, অপেরা এবং ইন্টারনেট এক্সপ্লোরার এটি এখনও সমর্থন করে না (পলিফিলটি সমাধানটিতে অন্তর্ভুক্ত করা হয়েছে)।
এই সমাধানে, এমন একটি বাক্স আছে যা লক্ষ্যমাত্রা (পর্যবেক্ষণ) is এটি যখন নজরে আসে তখন শিরোনামের উপরের অংশের বোতামটি লুকানো থাকে। বাক্সটি প্রদর্শনটি ছেড়ে যাওয়ার পরে এটি প্রদর্শিত হয়।
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>
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;
}
আমি মনে করি এটি এটি করার আরও কার্যকরী উপায়। ড্যানের উত্তর পুনরাবৃত্তির প্রসঙ্গে কাজ করে না।
এই উপাদানটি সমস্যার সমাধান করে যখন আপনার উপাদান অন্যদের মধ্যে থাকে তখন এইচটিএমএল ট্যাগ পর্যন্ত পুনরাবৃত্তিজনকভাবে কোনও স্তরের পরীক্ষা করে অন্যের স্ক্রোলযোগ্য ডিভগুলি থাকে এবং প্রথম মিথ্যাতে থামিয়ে দেয়।
/**
* 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)
);
};
অ্যান্ড্রয়েডে গুগল ক্রোম জুম করার সময় সর্বাধিক গৃহীত উত্তরগুলি কাজ করে না। অ্যান্ড্রয়েডে ক্রোমের জন্য অ্যাকাউন্টে ড্যানের উত্তরের সাথে মিশ্রণে ভিজ্যুয়ালভিউপোর্ট অবশ্যই ব্যবহার করা উচিত। নিম্নলিখিত উদাহরণটি কেবল উল্লম্ব চেকটি অ্যাকাউন্টে নেয় এবং উইন্ডো উচ্চতার জন্য 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)
স্ক্রোল হ্যান্ডলারের বাইরে ক্যাশে করা উচিত
পূর্ববর্তী উত্তরের বেশিরভাগ ব্যবহারগুলি এই পয়েন্টগুলিতে ব্যর্থ হচ্ছে:
-যখন কোনও উপাদানের কোনও পিক্সেল দৃশ্যমান হয় তবে " কোণে " নয়,
-যখন কোনও উপাদান ভিউপোর্টের চেয়ে বড় এবং কেন্দ্রিক হয় ,
- তাদের মধ্যে বেশিরভাগ কেবলমাত্র একটি দস্তাবেজ বা উইন্ডোর ভিতরে একক উপাদানের জন্য চেক করছেন ।
ঠিক আছে, এই সমস্ত সমস্যার জন্য আমি একটি সমাধান করেছি এবং এর পক্ষগুলি হ'ল:
-
visible
যখন আপনি কোনও দিক থেকে কেবল একটি পিক্সেল দেখায় এবং কোনও কোণে না থেকে ফিরে আসতে পারেন ,-
visible
ভিউপোর্টের চেয়ে বড় উপাদান থাকা অবস্থায় আপনি এখনও ফিরতে পারবেন ,-
parent element
আপনি আপনার চয়ন করতে পারেন বা আপনি স্বয়ংক্রিয়ভাবে এটি চয়ন করতে পারেন,উপর -Works পরিবর্তনশীল যোগ উপাদান খুব।
যদি আপনি নীচের স্নিপেটগুলি পরীক্ষা করে দেখেন যে 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
যা দেখতে ভিউপোর্ট চেক element3 ভেতরের পিক্সেলের থেকে বড় উপাদানের জন্য দরকারী হল:
আপনি দেখুন, আপনি এলিমেন্ট 3 এর ভিতরে থাকা অবস্থায় এটি দৃশ্যমান কিনা তা জানাতে ব্যর্থ হয়, কারণ আমরা কেবল এটিই পরীক্ষা করে নিচ্ছি যে উপাদানটি পাশ বা কোণ থেকে দৃশ্যমান কিনা ।
এবং এটিতে অন্তর্ভুক্ত রয়েছে crossSearchAlgorithm
যা visible
ভিউপোর্টের চেয়ে উপাদানটি বড় হলে আপনাকে এখনও ফিরে আসতে দেয় :
জেএসফিডেল এর সাথে খেলবেন: 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 () ব্যবহার করে এটি বের করেছিলাম।
এই কোডটি সম্পূর্ণ 'জেনেরিক' এবং এটি কাজ করার জন্য কেবল একবার লিখতে হবে (আপনি যে প্রতিটি উপাদানটি জানতে চান সেটি ভিউপোর্টে রয়েছে এটির জন্য আপনাকে এটি লিখতে হবে না)।
এই কোডটি কেবল ভোপপোর্টে অনুভূমিকভাবে নয় কিনা তা খতিয়ে দেখেছে see । এই ক্ষেত্রে, ভেরিয়েবল (অ্যারে) 'উপাদানগুলি' ভিউপোর্টে উল্লম্বভাবে যাচাই করার জন্য সমস্ত উপাদানগুলিকে ধারণ করে, সুতরাং আপনি যে কোনও উপাদান চাইলে ধরে নিন এবং সেগুলিকে সেখানে সংরক্ষণ করুন।
'লুপের জন্য', প্রতিটি উপাদান দিয়ে লুপ করে এবং ভিউপোর্টে এটি উল্লম্বভাবে রয়েছে কিনা তা পরীক্ষা করে। এই কোডটি ব্যবহারকারী প্রতিটি সময় স্ক্রোল কার্যকর করে! যদি 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.');
}
};
এটি আমার জন্য সহজ এবং ছোট সমাধানটি কাজ করেছে।
উদাহরণ : আপনি দেখতে চান যে মৌলিক উপাদানটিতে ওভারফ্লো স্ক্রোল রয়েছে has
$(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 স্ক্রিন হয় তবে এটি পরীক্ষা করে)
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
- আপনার কেবল ড্রিফ্টটি পাওয়া উচিত ...