වත්මන් දර්ශනපත්‍රයේ DOM අංගයක් දැකිය හැකිදැයි මා කියන්නේ කෙසේද?


969

DOM මූලද්‍රව්‍යයක් (HTML ලේඛනයක) දැනට දැකිය හැකිදැයි කීමට කාර්යක්ෂම ක්‍රමයක් තිබේද ( දර්ශනපත්‍රයේ දිස්වේ )?

(ප්‍රශ්නය ෆයර්ෆොක්ස් වෙත යොමු වේ.)


දෘශ්‍ය කිරීමෙන් ඔබ අදහස් කරන දේ මත රඳා පවතී. අනුචලන පිහිටීම අනුව එය දැනට පිටුවේ පෙන්වා ඇති බව ඔබ අදහස් කරන්නේ නම්, y ඕෆ්සෙට් මූලද්‍රව්‍ය සහ වත්මන් අනුචලන පිහිටීම මත පදනම්ව ඔබට එය ගණනය කළ හැකිය.
roryf

19
පැහැදිලි කිරීම: දැනට දර්ශනය වන සෘජුකෝණාස්රයේ මෙන් දෘශ්‍යමාන වේ. දෘශ්‍යමාන, සැඟවී නැති හෝ දර්ශනය නොවන පරිදි: කිසිවක් නැත? ඉසෙඩ් අනුපිළිවෙලෙහි වෙනත් දෙයක් පිටුපස නොපෙනෙන ලෙස පෙනෙනවාද?
ඇඩම් රයිට්

6
දැනට ප්‍රදර්ශනය කර ඇති සෘජුකෝණාස්රය තුළ මෙන්. ස්තූතියි. නැවත මුද්‍රණය කරන ලදි.
benzaita

2
මෙහි ඇති සියලුම පිළිතුරු මඟින් ඔවුන්ගේ මව් මූලද්‍රව්‍යයේ දෘශ්‍යමාන ප්‍රදේශයෙන් පිටත (පිටාර ගැලීම සැඟවී ඇති) නමුත් දර්ශනපත්‍ර ප්‍රදේශය තුළ ඇති අයිතම සඳහා ව්‍යාජ ධනාත්මක බවක් ලබා දෙන බව සලකන්න.
ඇන්ඩි ඊ

1
පිළිතුරු මිලියනයක් ඇති අතර බොහෝ ඒවා හාස්‍යජනක ලෙස දිගු ය. ලයිනර් දෙකක් සඳහා මෙහි බලන්න
ලියොන්හීස්

Answers:


353

යාවත්කාලීන කිරීම: කාලය ගමන් කරන අතර අපගේ බ්‍රව්සර් තිබේ. මෙම තාක්ෂණය තවදුරටත් නිර්දේශ නොකරන අතර 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
  );
}

1
පළ කරන ලද මුල් ශ්‍රිතයේ වැරැද්දක් තිබේ. එල් නැවත පැවරීමට පෙර පළල / උස සුරැකීමට අවශ්‍යයි ...
ප්‍රෙස්ටෝල්

16
මූලද්‍රව්‍යය අනුචලනය කළ හැකි කොට් in ාශයක ජීවත් වී දර්ශනයකින් ඉවතට ගියහොත් කුමක් කළ යුතුද?
amartynov

2
කරුණාකර පහත පිටපතෙහි නවතම අනුවාදය සමාලෝචනය කරන්න
ඩෑන්

1
@ අමර්ටිනොව්ගේ ප්‍රශ්නය ගැන ද කුතුහලයක්. මුතුන් මිත්තෙකුගේ මූලද්‍රව්‍යයක් පිටාර ගැලීම හේතුවෙන් මූලද්‍රව්‍යයක් සැඟවී ඇත්දැයි සරලව කිව හැක්කේ කෙසේදැයි යමෙක් දන්නවාද? දරුවා කොතරම් ගැඹුරට කැදැල්ලක සිටියත් මෙය හඳුනාගත හැකි නම් බෝනස්.
එරික් න්ගුයින්

1
OdedeadManN DOM හරහා පුනරාවර්තනය වීම කුප්‍රකට මන්දගාමී වේ. එය ප්‍රමාණවත් හේතුවකි, නමුත් getBoundingClientRectමූලද්‍රව්‍ය ඛණ්ඩාංක සොයා ගැනීමේ අරමුණ සඳහා බ්‍රව්සර් වෙළෙන්දෝ ද නිර්මාණය කර ඇත ... අප එය භාවිතා නොකරන්නේ ඇයි?
ප්‍රෙස්ටෝල්

1419

දැන් බොහෝ බ්‍රව්සර් 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: මෙම ක්‍රමය අවස්ථා දෙකක් හසුරුවන්නේ නැත:


6
මම මෙම විසඳුම භාවිතා කරමි ("බොටම්" යතුරු ලියනය ගැන පරිස්සම් වන්න). අප සලකා බලන මූලද්‍රව්‍යය තුළ රූප ඇති විට දැනුවත් විය යුතු දෙයක් ද තිබේ. මායිම් සෘජුකෝණාස්රය සඳහා නිශ්චිත අගයක් ලබා ගැනීම සඳහා ක්‍රෝම් (අවම වශයෙන්) රූපය පූරණය වන තෙක් බලා සිටිය යුතුය. ෆයර්ෆොක්ස් හි මෙම "ගැටලුවක්" නොමැති බව පෙනේ
ක්ලෝඩියෝ

4
ශරීරයේ ඇතුළත බහාලුමක් තුළ අනුචලනය සක්‍රීය කර ඇති විට එය ක්‍රියාත්මක වේද? උදාහරණයක් ලෙස එය මෙහි ක්‍රියාත්මක නොවේ - agaase.github.io/webpages/demo/isoncreen2.html isElementInViewport (document.getElementById ("innerele")). අනුචලනය සක්‍රීය කර ඇති බහාලුමක් තුළ innerele පවතී.
agaase

74
ගණනය කිරීම් උපකල්පනය කරන්නේ මූලද්රව්යය තිරයට වඩා කුඩා බවයි. ඔබට ඉහළ හෝ පුළුල් මූලද්‍රව්‍ය තිබේ නම්, එය භාවිතා කිරීම වඩාත් නිවැරදි විය හැකියreturn (rect.bottom >= 0 && rect.right >= 0 && rect.top <= (window.innerHeight || document.documentElement.clientHeight) && rect.left <= (window.innerWidth || document.documentElement.clientWidth));
Roonaan

11
ඉඟිය: මෙය jQuery සමඟ ක්‍රියාත්මක කිරීමට උත්සාහ කරන අයට, HTML DOM වස්තුවෙහි (උදා. isElementInViewport(document.getElementById('elem'))) සම්මත කිරීමට මිත්‍රශීලී මතක් කිරීමක් මිස jQuery වස්තුව (උදා. isElementInViewport($("#elem))) නොවේ. JQuery සමාන වන්නේ [0]එසේ එකතු කිරීමයි : isElementInViewport($("#elem)[0]).
ජිමිනි

12
el is not defined
එම්_විලට්

179

යාවත්කාලීන කරන්න

නවීන බ්‍රව්සර් වලදී, පහත සඳහන් ප්‍රතිලාභ ලබා දෙන ඡේදනය නිරීක්ෂක API පරීක්ෂා කිරීමට ඔබට අවශ්‍ය විය හැකිය :

  • අනුචලන සිදුවීම් වලට සවන්දීමට වඩා හොඳ කාර්ය සාධනය
  • හරස් වසම් අයිෆ්‍රේම් වල ක්‍රියා කරයි
  • මූලද්රව්යයක් තවත් බාධාවක් / ඡේදනය වන්නේ දැයි කිව හැකිය

ඉන්ටර්සෙක්ෂන් ඔබ්සර්වර් පූර්ණ ප්‍රමිතියක් කරා ගමන් කරමින් සිටින අතර දැනටමත් ක්‍රෝම් 51+, එජ් 15+ සහ ෆයර්ෆොක්ස් 55+ සඳහා සහය ලබා දී ඇති අතර එය සෆාරි සඳහා සංවර්ධනය වෙමින් පවතී. එය ද තිබෙන polyfill එළඹිය නොහැක.


පෙර පිළිතුර

ඩෑන් විසින් සපයන ලද පිළිතුර සමඟ ගැටළු කිහිපයක් ඇති අතර එය සමහර අවස්ථාවන්ට නුසුදුසු ප්‍රවේශයක් බවට පත් කළ හැකිය. මෙම කේතයන්ගෙන් සමහරක් ඔහුගේ පිළිතුරේ පතුල අසල පෙන්වා දී ඇත, ඔහුගේ කේතය මඟින් මූලද්‍රව්‍ය සඳහා ව්‍යාජ ධනාත්මක ප්‍රති give ල ලබා දෙනු ඇත:

  • පරීක්ෂා කරනු ලබන තැනැත්තා ඉදිරිපිට තවත් මූලද්‍රව්‍යයක් මගින් සඟවා ඇත
  • දෙමව්පියන්ගේ හෝ මුතුන් මිත්තන්ගේ මූලද්‍රව්‍යයේ දෘශ්‍යමාන ප්‍රදේශයෙන් පිටත
  • CSS clipදේපල භාවිතා කරමින් සඟවා ඇති මූලද්‍රව්‍යයක් හෝ එහි දරුවන්

සරල පරීක්ෂණයක පහත ප්‍රති results ල වලින් මෙම සීමාවන් පෙන්නුම් කෙරේ :

IsElementInViewport භාවිතා කරමින් පරීක්ෂණය අසාර්ථක විය

විසඳුම: 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 ලය:

IsElementVisible භාවිතා කරමින් පරීක්ෂණය සමත් විය

අමතර සටහන්

කෙසේ වෙතත්, මෙම ක්‍රමය තමන්ගේම සීමාවන් නොමැතිව නොවේ. නිදසුනක් ලෙස, එකම ස්ථානයේ වෙනත් මූලද්‍රව්‍යයකට වඩා අඩු z- දර්ශකයක් සමඟ පරීක්ෂා කරනු ලබන මූලද්‍රව්‍යයක් ඉදිරිපස ඇති මූලද්‍රව්‍යය එහි කිසිදු කොටසක් සැඟවී නොතිබුණද එය සැඟවුණු බව හඳුනා ගනු ඇත. තවමත්, මෙම ක්‍රමයට ඩෑන් ගේ විසඳුම ආවරණය නොවන සමහර අවස්ථාවල එහි භාවිතයන් ඇත.

දෙකම element.getBoundingClientRect()සහ document.elementFromPoint()CSSOM ක්‍රියාකාරී කෙටුම්පත් පිරිවිතරයේ කොටසක් වන අතර අවම වශයෙන් IE 6 සහ පසුව සහ බොහෝ ඩෙස්ක්ටොප් බ්‍රව්සර් වල දීර් time කාලයක් තිස්සේ සහය දක්වයි (වුවද, පරිපූර්ණ නොවේ). මෙම කාර්යයන් පිළිබඳ Quirksmode බලන්නවැඩි විස්තර සඳහා .

contains()document.elementFromPoint()දෘශ්‍යතාව සඳහා අප විසින් පරීක්ෂා කරනු ලබන මූලද්‍රව්‍යයේ ළමා නෝඩයක් ආපසු ලබා දුන් මූලද්‍රව්‍යය දැයි බැලීමට භාවිතා කරයි . ආපසු ලබා දුන් මූලද්‍රව්‍යය එකම මූලද්‍රව්‍යය නම් එය සත්‍ය වේ. මෙය චෙක්පත වඩාත් ශක්තිමත් කරයි. සියලුම ප්‍රධාන බ්‍රව්සර් වල එය සහය දක්වයි, ෆයර්ෆොක්ස් 9.0 එය එකතු කළ අන්තිමයා වේ. පැරණි ෆයර්ෆොක්ස් සහාය සඳහා, මෙම පිළිතුරේ ඉතිහාසය පරීක්ෂා කරන්න.

දෘශ්‍යතාව සඳහා මූලද්‍රව්‍යය වටා තවත් ලකුණු පරික්ෂා කිරීමට ඔබට අවශ්‍ය නම්, එනම්, මූලද්‍රව්‍යය 50% ට වඩා ආවරණය නොවන බව තහවුරු කර ගැනීම සඳහා, පිළිතුරේ අවසාන කොටස සැකසීමට බොහෝ දේ ගත නොවනු ඇත. කෙසේ වෙතත්, ඔබ සෑම පික්සෙල් එකක්ම 100% දෘශ්‍යමාන දැයි පරීක්ෂා කර බැලුවහොත් එය ඉතා මන්දගාමී වනු ඇති බව මතක තබා ගන්න.


2
ඔබ අදහස් කළේ doc.documentElement.clientWidth භාවිතා කිරීමටද? ඒ වෙනුවට එය 'document.documentElement' විය යුතුද? වෙනත් සටහනක, CSS 'ක්ලිප්' දේපල භාවිතා කරමින් ප්‍රවේශ්‍යතාව සඳහා මූලද්‍රව්‍යයක අන්තර්ගතය සැඟවීම වැනි අවස්ථා සඳහා භාවිතා කරන එකම ක්‍රමය මෙයයි: snook.ca/archives/html_and_css/hiding-content-for-accessibility
කෙවින් ලාම්පු

la ක්ලැම්පිං: හොඳ ඇල්ලීම, ස්තූතියි. මම එය භාවිතා කළ මගේ කේතයෙන් පිටත පිටපත් කළෙමිdoc අන්වර්ථයක් ලෙස කළdocument . ඔව්, මම කැමතියි මෙය අද්දර නඩු සඳහා හොඳ විසඳුමක් ලෙස සිතීමට.
ඇන්ඩි ඊ

2
මට නම් එය ක්‍රියාත්මක නොවේ. නමුත් පෙර පිළිතුරෙහි inViewport () FF හි වැඩ කරයි.
සත්‍ය ප්‍රකාශ්

10
මායිම් කොන් මගින් අපේක්ෂිත මූලද්‍රව්‍යය ආපසු නොලැබෙන බැවින්, වටකුරු කොන් හෝ පරිණාමනයක් යොදවා ඇත්දැයි මූලද්‍රව්‍යයේ කේන්ද්‍රය දෘශ්‍යමාන දැයි පරීක්ෂා කිරීම ද ප්‍රයෝජනවත් විය හැකිය:element.contains(efp(rect.right - (rect.width / 2), rect.bottom - (rect.height / 2)))
ජරෙඩ්

2
මා සඳහා යෙදවුම් මත වැඩ කළේ නැත (ක්‍රෝම් කැනරි 50). සමහර විට ස්වදේශික රවුන්ඩර් කොන් විය හැකිදැයි විශ්වාස නැද්ද? එය ක්‍රියා කිරීමට el.contains (efp (rect.left + 1, rect.top + 1)) සඳහා කෝඩ් තරමක් අඩු කිරීමට මට සිදු විය || el.contains (efp (rect.right-1, rect.top + 1)) || el.contains (efp (rect.right-1, rect.bottom-1)) || el.contains (efp (rect.left + 1, rect.bottom-1))
රේජැක්ස්

69

මම ඩෑන්ගේ පිළිතුර උත්සාහ කළා . කෙසේ වෙතත් , සීමාවන් තීරණය කිරීම සඳහා භාවිතා කරන වීජ ගණිතය යන්නෙන් අදහස් වන්නේ මූලද්‍රව්‍යය යන දෙකම විය යුතු බවයි 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() */;
}

33

පොදු සේවාවක් ලෙස:
නිවැරදි ගණනය කිරීම් සමඟ ඩෑන් ගේ පිළිතුර (මූලද්‍රව්‍යය> විශේෂයෙන් ජංගම දුරකථන තිරවල කවුළුව විය හැකිය), සහ නිවැරදි 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>

2
isElementPartiallyInViewportඉතා ප්‍රයෝජනවත් වේ. කදිම එකක්.
ආර්.ජේ. කත්බර්ට්සන්

IsElementInViewport (e) සඳහා: ඔබේ කේතය රූප පවා පටවන්නේ නැත, මෙය නිවැරදි ය: ශ්‍රිතය islementInViewport (e) {var t = e.getBoundingClientRect (); ආපසු t.top> = 0 && t.left> = 0 && t.bottom <= (window.innerHeight || document.documentElement.clientHeight) && t.right <= (window.innerWidth || document.documentElement.clientWidth) }
අරුන් චෞහාන්

1
R අරුන් චෞහාන්: මගේ කේත කිසිවක් රූප පටවන්නේ නැත, එබැවින් එය කළ යුත්තේ ඇයි, සහ සූත්‍රය නිවැරදි ය.
ස්ටෙෆාන් ස්ටීගර්

1
artargumon: හේතුව පැරණි බ්‍රව්සර් සඳහා සහාය වීමයි.
ස්ටෙෆාන් ස්ටීගර්

1
@StefanSteiger MDN අනුව එය IE9 සිට සහාය වෙනවා ඒක කෙලින්ම window.innerHeight භාවිතා කිරීමට (මගේ නඩුව අවම වශයෙන්) ප්රායෝගිකව ආරක්ෂිත එසේ. ස්තූතියි!
targumon

29

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නම් එය නැවත පැමිණේ .


28

මගේ කෙටි හා වේගවත් අනුවාදය:

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/


4
මගේ විසඳුම වඩාත් කෑදර හා වේගවත් ය, මූලද්‍රව්‍යයට ඕනෑම පික්සෙල් දර්ශන තලයක ඇති විට එය අසත්‍ය වේ.
එරික් චෙන්

1
මම එයට කැමතියි. සංක්ෂිප්ත. පළමු පේළියේ ඔබට ශ්‍රිතයේ නම සහ වරහන් අතර ඇති වරහන් ඉවත් කළ හැකිය. එම අවකාශයන්ට කිසි විටෙකත් කැමති නැත. සමහර විට එය මගේ පෙළ සංස්කාරකය පමණක් වන අතර එය වර්ණ කේත සියල්ලම කියවීමට පහසු කරයි. aaa (arg) {ප්‍රකාශ} එය වේගයෙන් ක්‍රියාත්මක නොවන බව මම දනිමි.
YK

21

ක්‍රියාකාරීත්වයේ 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
    }
});

1
If ප්‍රකාශය වැසීමට කැරලි වරහන ප්‍රමාණවත් වේද?
කැලසිර්

1
සමාන පන්තියක බහු අංග සමඟ එය ක්‍රියා කිරීමට මට නොහැකි විය.
විස් ඔෆ් ඕස්

1
WTheWhizofOz ඔබ විසින් ගෙන එන ලද වෙනත් භාවිත අවස්ථා පිළිබඳ උදාහරණ ලබා දීම සඳහා මම මගේ පිළිතුර යාවත්කාලීන කර ඇත. සුභ පැතුම්.
r3wt

10

නව ඡේදනය නිරීක්ෂක 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>


3
හොඳ ක්‍රියාත්මක කිරීමක් වන අතර, මෙම පිළිතුරෙහි ඇති සබැඳියට අනුව එය HTML<!DOCTYPE html>
Alon Eitan

IntersectionObserverඑය පර්යේෂණාත්මක අංගයක් බව සලකන්න (එය අනාගතයේදී වෙනස් විය හැකිය).
කාර්තික් චින්තලා

2
Arth කාර්තික් චින්තලා - IE හැර සෑම බ්‍රව්සරයකම එය සහය දක්වයි - තවද බහු පිරවුමක් ද ඇත.
රැන්ඩි කැස්බර්න්

වෙනස්වීම් පමණක් හඳුනාගන්නා බැවින් OP හි ප්‍රශ්නයට ආමන්ත්‍රණය නොකරයි : IntersectionObserverමූලයට සාපේක්ෂව ඉලක්කය චලනය කිරීමෙන් පසුව පමණක් ඇමතුම් ලබා ගනී.
බ්‍රැන්ඩන් හිල්

ඇමතුම් observeසිදුවීම වහාම ක්‍රියාත්මක වන විට , ලුහුබැඳ ඇති මූලද්‍රව්‍යයේ වර්තමාන ඡේදනය වීමේ තත්වය ඔබට කියනු ඇත. එබැවින්, යම් ආකාරයකින් - එය ආමන්ත්‍රණය කරයි.
මෙස්කලිටෝ

8

මට මෙහි හමු වූ සියලුම පිළිතුරු පරීක්ෂා කරන්නේ මූලද්‍රව්‍යය වත්මන් දර්ශනපත්‍රයේ ස්ථානගත වී ඇත්ද යන්න පමණි . නමුත් එය දෘශ්‍යමාන බව එයින් අදහස් නොවේ .
දී ඇති මූලද්‍රව්‍යය පිරී ඉතිරී යන අන්තර්ගතයක් සහිත අංශයක් තුළ තිබේ නම් සහ එය නොපෙනී යයි නම් කුමක් කළ යුතුද?

එය විසඳීම සඳහා, මෙම මූලද්‍රව්‍යය සියලුම දෙමව්පියන් විසින් අඩංගු දැයි පරීක්ෂා කර බැලිය යුතුය.
මගේ විසඳුම එය හරියටම කරයි:

මූලද්‍රව්‍යය කොපමණ ප්‍රමාණයක් දෘශ්‍යමාන විය යුතුද යන්න නියම කිරීමටද එය ඔබට ඉඩ සලසයි.

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 හි අත්හදා බැලුවෙමි.


8

මෙහි පිළිගත් පිළිතුර බොහෝ භාවිත අවස්ථා සඳහා ඕනෑවට වඩා සංකීර්ණ බව මට පෙනී ගියේය. මෙම කේතය කාර්යය හොඳින් කරයි (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)අනුචලන හසුරුවන්නාට පිටතින් හැඹිලි ගත යුතුය .
සෑම්

4

Element.getBoundingClientRect () හි සහාය ලෙස සරලම විසඳුම පරිපූර්ණ වී ඇත :

function isInView(el) {
    let box = el.getBoundingClientRect();
    return box.top < window.innerHeight && box.bottom >= 0;
}

ජංගම බ්‍රව්සර් වල මෙය හැසිරෙන්නේ කෙසේද? ඒවායින් බොහොමයක් දර්ශනපත්‍රය සම්බන්ධයෙන් දෝෂ සහිත වන අතර, ඒවායේ ශීර්ෂකය අනුචලනය වන විට ඉහළට හෝ පහළට ගමන් කරයි, සහ යතුරුපුවරුව පෙන්වන විට වෙනස් හැසිරීම, එය ඇන්ඩ්‍රොයිඩ් හෝ අයෝස් යනාදිය මත පදනම්ව
Kev

EKev ඔබ මෙම ක්‍රමය අමතන විට එය හොඳින් ක්‍රියාත්මක විය යුතුය. ඔබ එය අමතා කවුළුවේ ප්‍රමාණය වෙනස් කළහොත්, ප්‍රති result ලය තවදුරටත් නිවැරදි නොවනු ඇත. ඔබට අවශ්‍ය ක්‍රියාකාරීත්වය අනුව සෑම ප්‍රමාණයකටම ඔබට එය ඇමතිය හැකිය. ඔබගේ විශේෂිත භාවිත නඩුව ගැන වෙනම ප්‍රශ්නයක් ඇසීමට නිදහස්ව සිටින්න.
ලියොන්හීස්

3

මම හිතන්නේ මෙය වඩාත් ක්‍රියාකාරී ක්‍රමයක්. ඩෑන් ගේ පිළිතුර පුනරාවර්තන සන්දර්භයක් තුළ ක්‍රියා නොකරයි.

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)
    );
};

3

ඇන්ඩ්‍රොයිඩ් හි ගූගල් ක්‍රෝම් හි විශාලනය කිරීමේදී වඩාත්ම පිළිගත් පිළිතුරු ක්‍රියා නොකරයි. ඇන්ඩ්‍රොයිඩ් හි ක්‍රෝම් සඳහා ගිණුම්ගත කිරීම සඳහා ඩෑන් ගේ පිළිතුර සමඟ ඒකාබද්ධව දෘශ්‍ය වීව්පෝට් භාවිතා කළ යුතුය. පහත උදාහරණය සිරස් පරීක්ෂාව පමණක් සැලකිල්ලට ගෙන කවුළු උස සඳහා 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);

2

මෙන්න මගේ විසඳුම. අනුචලනය කළ හැකි බහාලුමක් තුළ මූලද්‍රව්‍යයක් සඟවා ඇත්නම් එය ක්‍රියා කරයි.

මෙන්න නිරූපණයක් (කවුළුව නැවත ප්‍රමාණ කිරීමට උත්සාහ කරන්න)

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 අක්ෂයේ දෘශ්‍යමාන දැයි පරීක්ෂා කිරීම පමණි (අනුචලන අජැක්ස් පැටවීම-වැඩි වාර්තා විශේෂාංගයක් සඳහා).


2

ඩෑන් ගේ විසඳුම මත පදනම්ව , එකම පිටුවක කිහිප වතාවක් භාවිතා කිරීම පහසු වන පරිදි ක්‍රියාත්මක කිරීම පිරිසිදු කිරීමට මට සිදු විය:

$(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)අනුචලන හසුරුවන්නාට පිටතින් හැඹිලි ගත යුතුය
ඇඩම් රෙහාල්

2

පෙර පිළිතුරු වල බොහෝ භාවිතයන් මෙම අවස්ථා වලදී අසමත් වේ:

මූලද්‍රව්‍යයක ඕනෑම පික්සෙල් දෘශ්‍යමාන වන නමුත් “ කොනක් ” නොවේ,

මූලද්‍රව්‍යයක් දර්ශනපත්‍රයට වඩා විශාල වන අතර කේන්ද්‍රගත වූ විට ,

ඔවුන්ගෙන් බොහෝ දෙනෙක් පරික්ෂා කරන්නේ ලේඛනයක් හෝ කවුළුවක් තුළ ඇති ඒකීය මූලද්‍රව්‍යයක් සඳහා පමණි .

හොඳයි, මේ සියලු ගැටලු සඳහා මම විසඳුමක් ඇති අතර ප්ලස් පැති:

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 ලදායී වේ.


1

වඩා හොඳ විසඳුමක්:

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;
}

12
ඔබේ අනුවාදය වඩා හොඳ වන්නේ මන්දැයි ඔබ උත්සාහ කර පැහැදිලි කළ යුතුය. එය පවතින විට, එය අනෙක් විසඳුම් මෙන් අඩු හෝ වැඩි වශයෙන් පෙනේ.
ඇන්ඩි ඊ

1
විශිෂ්ට විසඳුමක් එයට බොක්ස් / ස්ක්‍රෝල් කන්ටේනරයක් ඇති අතර එය වින්ඩෝව භාවිතා නොකරයි (එය නිශ්චිතව දක්වා නොමැති නම් පමණි). අනුපාතයට වඩා කේතය දෙස බලන්න එය වඩා විශ්වීය විසඳුමකි (එය බොහෝ සෙවීමක් විය)
ටෙටර්

1

එය ලබා ගත හැකි තරම් සරල, IMO:

function isVisible(elem) {
  var coords = elem.getBoundingClientRect();
  return Math.abs(coords.top) <= coords.height;
}

0

මව් මූලද්‍රව්‍යයක වර්තමාන දර්ශනපත්‍රයේ මූලද්‍රව්‍යයක් දෘශ්‍යමාන වන්නේ දැයි පවසන ශ්‍රිතයක් මෙන්න :

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
    );
}

0

මූලද්‍රව්‍යයක් අවම වශයෙන් අර්ධ වශයෙන් පෙනෙන්නේ දැයි මෙය පරීක්ෂා කරයි (සිරස් මානය):

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}
}

0

මට එකම ප්‍රශ්නය ඇති අතර 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.');
   }
};

0

මෙය මා වෙනුවෙන් වැඩ කර ඇති පහසු සහ කුඩා විසඳුමයි.

උදාහරණය : පිටාර අනුචලනය ඇති මව් මූලද්‍රව්‍යයේ මූලද්‍රව්‍යය දැකිය හැකිදැයි බැලීමට ඔබට අවශ්‍යය.

$(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');
     }
})

0

මෙහි ඇති සියලුම පිළිතුරු තීරණය කරනුයේ කිසියම් ආකාරයකින් දෘශ්‍යමාන නොවී, මූලද්‍රව්‍යය සම්පූර්ණයෙන්ම දර්ශනපත්‍රයේ අඩංගු වේද යන්නයි. නිදසුනක් ලෙස, රූපයේ අඩක් පමණක් දර්ශනයේ පතුලේ දැකිය හැකි නම්, මෙහි ඇති විසඳුම් අසාර්ථක වනු ඇත.

මම කම්මැලි පැටවීම සිදුකරන ස්ථානයක් භාවිතා කළෙමි 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));

මෙය මූලික වශයෙන් පරික්ෂා කරන්නේ ඉහළ හෝ පහළ මායිම ස්වාධීනව දර්ශනපත්‍රයේ තිබේද යන්නයි. ප්‍රතිවිරුද්ධ කෙළවර පිටත විය හැකි නමුත් එක් කෙළවරක් පවතින තාක් එය අවම වශයෙන් අර්ධ වශයෙන් “දෘශ්‍යමාන” වේ.


-1

මම මෙම ශ්‍රිතය භාවිතා කරමි (එය පරික්ෂා කරන්නේ 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;
    }

}

-3

ඒ හා සමාන අභියෝගයක් සඳහා, 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- ඔබ ප්ලාවනය ලබා ගත යුතුය ...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.