DOM මූලද්රව්යයක් (HTML ලේඛනයක) දැනට දැකිය හැකිදැයි කීමට කාර්යක්ෂම ක්රමයක් තිබේද ( දර්ශනපත්රයේ දිස්වේ )?
(ප්රශ්නය ෆයර්ෆොක්ස් වෙත යොමු වේ.)
DOM මූලද්රව්යයක් (HTML ලේඛනයක) දැනට දැකිය හැකිදැයි කීමට කාර්යක්ෂම ක්රමයක් තිබේද ( දර්ශනපත්රයේ දිස්වේ )?
(ප්රශ්නය ෆයර්ෆොක්ස් වෙත යොමු වේ.)
Answers:
යාවත්කාලීන කිරීම: කාලය ගමන් කරන අතර අපගේ බ්රව්සර් තිබේ. මෙම තාක්ෂණය තවදුරටත් නිර්දේශ නොකරන අතර 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 (සහ පසුව), iOS 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);
}
*/
ඔබ කිසියම් DOM වෙනස් කිරීම් කරන්නේ නම්, ඒවාට ඔබේ මූලද්රව්යයේ දෘශ්යතාව වෙනස් කළ හැකිය.
මාර්ගෝපදේශ සහ පොදු අන්තරායන්:
සමහර විට ඔබට පිටු විශාලනය / ජංගම උපාංගය සොයා ගැනීමට අවශ්යද? jQuery විසින් විශාලනය / පින්ච් හරස් බ්රව්සරය හැසිරවිය යුතුය , එසේ නොමැතිනම් පළමු හෝ දෙවන සබැඳිය ඔබට උදව් වනු ඇත.
ඔබ DOM වෙනස් කරන්නේ නම් , එය මූලද්රව්යයේ දෘශ්යතාවයට බලපායි. ඔබ එය පාලනය කර handler()
අතින් අමතන්න . අවාසනාවට, අපට හරස් බ්රව්සර onrepaint
සිදුවීමක් නොමැත. අනෙක් අතට, මූලද්රව්යයක දෘශ්යතාව වෙනස් කළ හැකි DOM වෙනස් කිරීම් මත පමණක් ප්රශස්තිකරණය කිරීමට සහ නැවත පරීක්ෂා කිරීමට අපට ඉඩ සලසයි.
කවදාවත් එය jQuery $ (ලේඛනය) තුළ භාවිතා නොකරන්න. සූදානම් () පමණක්, වගකීමක් නොමැති නිසා CSS යෙදී ඇත මේ මොහොතේ ඇත. ඔබේ කේතයට දෘ CS තැටියක ඔබේ 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
නවීන බ්රව්සර් වලදී, පහත සඳහන් ප්රතිලාභ ලබා දෙන ඡේදනය නිරීක්ෂක API පරීක්ෂා කිරීමට ඔබට අවශ්ය විය හැකිය :
ඉන්ටර්සෙක්ෂන් ඔබ්සර්වර් පූර්ණ ප්රමිතියක් කරා ගමන් කරමින් සිටින අතර දැනටමත් ක්රෝම් 51+, එජ් 15+ සහ ෆයර්ෆොක්ස් 55+ සඳහා සහය ලබා දී ඇති අතර එය සෆාරි සඳහා සංවර්ධනය වෙමින් පවතී. එය ද තිබෙන polyfill එළඹිය නොහැක.
ඩෑන් විසින් සපයන ලද පිළිතුර සමඟ ගැටළු කිහිපයක් ඇති අතර එය සමහර අවස්ථාවන්ට නුසුදුසු ප්රවේශයක් බවට පත් කළ හැකිය. මෙම කේතයන්ගෙන් සමහරක් ඔහුගේ පිළිතුරේ පතුල අසල පෙන්වා දී ඇත, ඔහුගේ කේතය මඟින් මූලද්රව්ය සඳහා ව්යාජ ධනාත්මක ප්රති give ල ලබා දෙනු ඇත:
clip
දේපල භාවිතා කරමින් සඟවා ඇති මූලද්රව්යයක් හෝ එහි දරුවන්සරල පරීක්ෂණයක පහත ප්රති results ල වලින් මෙම සීමාවන් පෙන්නුම් කෙරේ :
isElementVisible()
පහත දැක්වෙන පරීක්ෂණ ප්රති result ල සහ කේතයේ සමහර කොටස් පිළිබඳ පැහැදිලි කිරීමක් සමඟ එම ගැටළුවලට විසඳුමක් මෙන්න.
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/
සහ ප්රති result ලය:
කෙසේ වෙතත්, මෙම ක්රමය තමන්ගේම සීමාවන් නොමැතිව නොවේ. නිදසුනක් ලෙස, එකම ස්ථානයේ වෙනත් මූලද්රව්යයකට වඩා අඩු z- දර්ශකයක් සමඟ පරීක්ෂා කරනු ලබන මූලද්රව්යයක් ඉදිරිපස ඇති මූලද්රව්යය එහි කිසිදු කොටසක් සැඟවී නොතිබුණද එය සැඟවුණු බව හඳුනා ගනු ඇත. තවමත්, මෙම ක්රමයට ඩෑන් ගේ විසඳුම ආවරණය නොවන සමහර අවස්ථාවල එහි භාවිතයන් ඇත.
දෙකම element.getBoundingClientRect()
සහ document.elementFromPoint()
CSSOM ක්රියාකාරී කෙටුම්පත් පිරිවිතරයේ කොටසක් වන අතර අවම වශයෙන් IE 6 සහ පසුව සහ බොහෝ ඩෙස්ක්ටොප් බ්රව්සර් වල දීර් time කාලයක් තිස්සේ සහය දක්වයි (වුවද, පරිපූර්ණ නොවේ). මෙම කාර්යයන් පිළිබඳ Quirksmode බලන්නවැඩි විස්තර සඳහා .
contains()
document.elementFromPoint()
දෘශ්යතාව සඳහා අප විසින් පරීක්ෂා කරනු ලබන මූලද්රව්යයේ ළමා නෝඩයක් ආපසු ලබා දුන් මූලද්රව්යය දැයි බැලීමට භාවිතා කරයි . ආපසු ලබා දුන් මූලද්රව්යය එකම මූලද්රව්යය නම් එය සත්ය වේ. මෙය චෙක්පත වඩාත් ශක්තිමත් කරයි. සියලුම ප්රධාන බ්රව්සර් වල එය සහය දක්වයි, ෆයර්ෆොක්ස් 9.0 එය එකතු කළ අන්තිමයා වේ. පැරණි ෆයර්ෆොක්ස් සහාය සඳහා, මෙම පිළිතුරේ ඉතිහාසය පරීක්ෂා කරන්න.
දෘශ්යතාව සඳහා මූලද්රව්යය වටා තවත් ලකුණු පරික්ෂා කිරීමට ඔබට අවශ්ය නම්, එනම්, මූලද්රව්යය 50% ට වඩා ආවරණය නොවන බව තහවුරු කර ගැනීම සඳහා, පිළිතුරේ අවසාන කොටස සැකසීමට බොහෝ දේ ගත නොවනු ඇත. කෙසේ වෙතත්, ඔබ සෑම පික්සෙල් එකක්ම 100% දෘශ්යමාන දැයි පරීක්ෂා කර බැලුවහොත් එය ඉතා මන්දගාමී වනු ඇති බව මතක තබා ගන්න.
doc
අන්වර්ථයක් ලෙස කළdocument
. ඔව්, මම කැමතියි මෙය අද්දර නඩු සඳහා හොඳ විසඳුමක් ලෙස සිතීමට.
element.contains(efp(rect.right - (rect.width / 2), rect.bottom - (rect.height / 2)))
මම ඩෑන්ගේ පිළිතුර උත්සාහ කළා . කෙසේ වෙතත් , සීමාවන් තීරණය කිරීම සඳහා භාවිතා කරන වීජ ගණිතය යන්නෙන් අදහස් වන්නේ මූලද්රව්යය යන දෙකම විය යුතු බවයි 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() */;
}
පොදු සේවාවක් ලෙස:
නිවැරදි ගණනය කිරීම් සමඟ ඩෑන් ගේ පිළිතුර (මූලද්රව්යය> විශේෂයෙන් ජංගම දුරකථන තිරවල කවුළුව විය හැකිය), සහ නිවැරදි 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;
}
අවශ්ය පරිදි jsFiddle: https://jsfiddle.net/on1g619L/1/
ක්රියාකාරීත්වයේ jQuery කේන්ද්රීය අනුවාදයක් නොතිබීම මට කරදරයක් විය . ඩෑන් ගේ විසඳුම හමු වූ විට , 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
}
});
නව ඡේදනය නිරීක්ෂක API මෙම ප්රශ්නය ඉතා කෙලින්ම ආමන්ත්රණය කරයි.
මෙම විසඳුමට සෆාරි, ඔපෙරා සහ ඉන්ටර්නෙට් එක්ස්ප්ලෝරර් තවමත් සහාය නොදක්වන බැවින් පොලිෆිල් එකක් අවශ්ය වේ (පොලිෆිල් විසඳුමට ඇතුළත් කර ඇත).
මෙම විසඳුම තුළ, ඉලක්කය (නිරීක්ෂණය කරන ලද) නොපෙනෙන කොටුවක් තිබේ. එය බැලූ විට, ශීර්ෂයේ ඉහළින් ඇති බොත්තම සැඟවී ඇත. කොටුව දර්ශනයෙන් ඉවත් වූ පසු එය පෙන්වනු ලැබේ.
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)
);
};
ඇන්ඩ්රොයිඩ් හි ගූගල් ක්රෝම් හි විශාලනය කිරීමේදී වඩාත්ම පිළිගත් පිළිතුරු ක්රියා නොකරයි. ඇන්ඩ්රොයිඩ් හි ක්රෝම් සඳහා ගිණුම්ගත කිරීම සඳහා ඩෑන් ගේ පිළිතුර සමඟ ඒකාබද්ධව දෘශ්ය වීව්පෝට් භාවිතා කළ යුතුය. පහත උදාහරණය සිරස් පරීක්ෂාව පමණක් සැලකිල්ලට ගෙන කවුළු උස සඳහා 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;
};
මට අවශ්ය වූයේ එය Y අක්ෂයේ දෘශ්යමාන දැයි පරීක්ෂා කිරීම පමණි (අනුචලන අජැක්ස් පැටවීම-වැඩි වාර්තා විශේෂාංගයක් සඳහා).
ඩෑන් ගේ විසඳුම මත පදනම්ව , එකම පිටුවක කිහිප වතාවක් භාවිතා කිරීම පහසු වන පරිදි ක්රියාත්මක කිරීම පිරිසිදු කිරීමට මට සිදු විය:
$(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()
);
}
});
මම එය භාවිතා කරන ආකාරය නම්, මූලද්රව්යය දර්ශනය වන විට, මම CSS යතුරු රාමු සජීවිකරණයක් අවුලුවන පන්තියක් එක් කරමි. එය ඉතා සරල වන අතර පිටුවක කොන්දේසි සහිතව සජීවිකරණය කිරීමට ඔබට 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
දසුන් තොට චෙක්පත වඩා විශාල මූලද්රව්ය සඳහා usefull වන දකින්න අභ්යන්තර පික්සල element3:
ඔබට පෙනේ, ඔබ මූලද්රව්යය 3 තුළ සිටින විට එය දෘශ්යමානද නැද්ද යන්න කීමට අපොහොසත් වේ, මන්ද අප පරීක්ෂා කරන්නේ මූලද්රව්යය පැතිවලින් හෝ කොන් වලින් දැකිය හැකිද යන්නයි .
දර්ශන පුවරුවට වඩා මූලද්රව්යය විශාල වූ විට crossSearchAlgorithm
නැවත පැමිණීමට ඉඩ සලසන මෙයට ඇතුළත් වේ visible
:
JSFiddle සමඟ සෙල්ලම් කිරීමට: http://jsfiddle.net/BerkerYuceer/grk5az2c/
මෙම කේතය සෑදී ඇත්තේ මූලද්රව්යයේ කිසියම් කොටසක් දර්ශනයෙන් පෙන්වන්නේද නැද්ද යන්න වඩාත් නිවැරදි තොරතුරු සඳහා ය. කාර්ය සාධන විකල්ප සඳහා හෝ සිරස් විනිවිදක සඳහා පමණක් මෙය භාවිතා නොකරන්න! මෙම කේතය නඩු ඇඳීමේදී වඩාත් is ලදායී වේ.
වඩා හොඳ විසඳුමක්:
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;
}
එය ලබා ගත හැකි තරම් සරල, IMO:
function isVisible(elem) {
var coords = elem.getBoundingClientRect();
return Math.abs(coords.top) <= coords.height;
}
මව් මූලද්රව්යයක වර්තමාන දර්ශනපත්රයේ මූලද්රව්යයක් දෘශ්යමාන වන්නේ දැයි පවසන ශ්රිතයක් මෙන්න :
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 () භාවිතා කිරීමෙන් එය හදුනා ගන්නා ලදි.
මෙම කේතය සම්පුර්ණයෙන්ම 'ජනක' වන අතර එය ක්රියාත්මක වීමට එක් වරක් පමණක් ලිවිය යුතුය (ඔබට දැන ගැනීමට අවශ්ය සෑම අංගයක් සඳහාම එය ලිවිය යුතු නැත.
මෙම කේතය, චෙක්පත් වලින් පමණක් එය දසුන් තොට දී සිරස් අතට නම් බලන්න නොවේ තිරස් අතට . මෙම අවස්ථාවෙහිදී, විචල්ය (අරාව) 'මූලද්රව්ය' ඔබ පරීක්ෂා කරන සියලුම මූලද්රව්ය දර්ශන තලයේ සිරස් අතට තබා ඇති බැවින් ඔබට අවශ්ය ඕනෑම මූලද්රව්යයක් අල්ලාගෙන ඒවා එහි ගබඩා කරන්න.
'For loop', එක් එක් මූලද්රව්යය හරහා ලූප වී එය දර්ශන තලයේ සිරස් අතට තිබේදැයි පරීක්ෂා කරයි. පරිශීලකයා අනුචලනය කරන සෑම අවස්ථාවකම මෙම කේතය ක්රියාත්මක වේ ! 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 බොහෝ විට 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;
}
}
ඒ හා සමාන අභියෝගයක් සඳහා, scrollIntoViewIfNeeded () සඳහා බහු පිරවුමක් නිරාවරණය කරන මෙම සාරාංශය මම සැබවින්ම භුක්ති වින්දා .
පිළිතුරු දීමට අවශ්ය සියලුම කුං ෆු මෙම කොටස තුළ ඇත:
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
- ඔබ ප්ලාවනය ලබා ගත යුතුය ...