Як перевірити, чи не є елемент поза екраном


81

Мені потрібно перевірити за допомогою jQuery, чи не випадає елемент DIV за межі екрану. Елементи видно та відображаються відповідно до атрибутів CSS, але їх можна навмисно розмістити поза екраном, виконавши:

position: absolute; 
left: -1000px; 
top: -1000px;

Я не міг використовувати :visibleселектор jQuery , оскільки елемент має ненульову висоту та ширину.

Я не роблю нічого химерного. Це абсолютне розміщення позиції - це спосіб, яким мій фреймворк Ajax реалізує сховання / показ деяких віджетів.


Я дав відповідь на цей питання, а також на цьому «дублікат» питання: stackoverflow.com/questions/5353934 / ...
Tokimon

Відповіді:


136

Залежить від того, що ви розумієте як "поза екраном". Це в межах області перегляду або в межах визначених меж вашої сторінки?

За допомогою Element.getBoundingClientRect () ви можете легко визначити, чи знаходиться ваш елемент у межах вашого вікна перегляду (тобто на екрані чи поза екраном):

jQuery.expr.filters.offscreen = function(el) {
  var rect = el.getBoundingClientRect();
  return (
           (rect.x + rect.width) < 0 
             || (rect.y + rect.height) < 0
             || (rect.x > window.innerWidth || rect.y > window.innerHeight)
         );
};

Потім ви можете використовувати це кількома способами:

// returns all elements that are offscreen
$(':offscreen');

// boolean returned if element is offscreen
$('div').is(':offscreen');

2
Мені це сподобалося, але воно ламається, якщо ваш елемент знаходиться всередині прокручуваного контейнера - елемент внизу 2-екранного DIV завжди буде "поза екраном", оскільки висота вікна менше, ніж offsetTop елемента.
Coderer

@scurker Я не міг змусити це працювати. Ось моє запитання SO (з jsFiddle) про цю проблему: stackoverflow.com/questions/26004098 / ...
crashwap

я помиляюся тут, думаючи, що цього не станеться, якщо el розташував батьківського (абсолютного чи відносного) перед тілом?
fekiri malek

@fekirimalek Ви маєте рацію, я оновив приклад, щоб пояснити це
scurker

7
Зауважте, що наразі (січень 2017 р.) Це не буде працювати принаймні в Chrome, оскільки Element.getBoundingClientRect () має властивості top, right, bottom і left замість x і y.
Асу,

18

Тут є плагін jQuery, який дозволяє користувачам перевірити, чи не потрапляє елемент до видимого вікна перегляду браузера, беручи до уваги позицію прокрутки браузера.

$('#element').visible();

Ви також можете перевірити наявність часткової видимості:

$('#element').visible( true);

Одним недоліком є ​​те, що він працює лише з вертикальним позиціонуванням / прокруткою, хоча він повинен бути досить простим, щоб додати горизонтальне позиціонування в суміш.


Це ДУЖЕ легкий плагін. Мені вдалося отримати фіксовану панель навігації при прокрутці вгору та оперативно працювати за лічені хвилини після її додавання. Чудова пропозиція.
Nappstir

Цей плагін дуже легкий і досить простий у реалізації. Вирішив проблему, яку я мав із підменю.
Тео Орфанос

9

Не потрібно плагіна, щоб перевірити, чи не знаходиться порт перегляду.

var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0)
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
var d = $(document).scrollTop();

$.each($("div"),function(){
    p = $(this).position();
    //vertical
    if (p.top > h + d || p.top > h - d){
        console.log($(this))
    }
    //horizontal
    if (p.left < 0 - $(this).width() || p.left > w){
        console.log($(this))
    }
});

1
Це спрацювало б, якщо ви використовували $(this).offsetзамість $this.position. Зараз це просто обчислення відстані від батьківського елемента, що може бути div, який ідеально обертає його.
Райан Шилінгтон,

7

Ну ... Я знайшов деякі проблеми в кожному запропонованому вирішенні тут.

  • Ви повинні мати можливість вибирати, чи хочете ви, щоб на екрані був весь елемент або будь-яка його частина
  • Запропоновані рішення виходять з ладу, якщо елемент вищий / ширший за вікно і, як би, охоплює вікно браузера.

Ось моє рішення, яке включає jQuery .fnфункцію екземпляра та expression. Я створив у своїй функції більше змінних, ніж міг, але для складної логічної задачі я люблю ділити її на менші, чітко названі частини.

Я використовую getBoundingClientRectметод, який повертає позицію елемента відносно області перегляду, тому мені не потрібно дбати про позицію прокрутки

Використання :

$(".some-element").filter(":onscreen").doSomething();
$(".some-element").filter(":entireonscreen").doSomething();
$(".some-element").isOnScreen(); // true / false
$(".some-element").isOnScreen(true); // true / false (partially on screen)
$(".some-element").is(":onscreen"); // true / false (partially on screen)
$(".some-element").is(":entireonscreen"); // true / false 

Джерело :

$.fn.isOnScreen = function(partial){

    //let's be sure we're checking only one element (in case function is called on set)
    var t = $(this).first();

    //we're using getBoundingClientRect to get position of element relative to viewport
    //so we dont need to care about scroll position
    var box = t[0].getBoundingClientRect();

    //let's save window size
    var win = {
        h : $(window).height(),
        w : $(window).width()
    };

    //now we check against edges of element

    //firstly we check one axis
    //for example we check if left edge of element is between left and right edge of scree (still might be above/below)
    var topEdgeInRange = box.top >= 0 && box.top <= win.h;
    var bottomEdgeInRange = box.bottom >= 0 && box.bottom <= win.h;

    var leftEdgeInRange = box.left >= 0 && box.left <= win.w;
    var rightEdgeInRange = box.right >= 0 && box.right <= win.w;


    //here we check if element is bigger then window and 'covers' the screen in given axis
    var coverScreenHorizontally = box.left <= 0 && box.right >= win.w;
    var coverScreenVertically = box.top <= 0 && box.bottom >= win.h;

    //now we check 2nd axis
    var topEdgeInScreen = topEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );
    var bottomEdgeInScreen = bottomEdgeInRange && ( leftEdgeInRange || rightEdgeInRange || coverScreenHorizontally );

    var leftEdgeInScreen = leftEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );
    var rightEdgeInScreen = rightEdgeInRange && ( topEdgeInRange || bottomEdgeInRange || coverScreenVertically );

    //now knowing presence of each edge on screen, we check if element is partially or entirely present on screen
    var isPartiallyOnScreen = topEdgeInScreen || bottomEdgeInScreen || leftEdgeInScreen || rightEdgeInScreen;
    var isEntirelyOnScreen = topEdgeInScreen && bottomEdgeInScreen && leftEdgeInScreen && rightEdgeInScreen;

    return partial ? isPartiallyOnScreen : isEntirelyOnScreen;

};

$.expr.filters.onscreen = function(elem) {
  return $(elem).isOnScreen(true);
};

$.expr.filters.entireonscreen = function(elem) {
  return $(elem).isOnScreen(true);
};

1
Я отримую make_footer_down.js: 8 Uncaught TypeError: Не вдається прочитати властивість 'getBoundingClientRect' з undefined при спробі використовувати там ur-функції.
Людвіг Ш

Привіт, Lurr ... Я спробував з $ ("# divId"). IsOnScreen (true); де 'divId' був поза екраном, і він повернув мені 'false'; отже, я відчуваю, що це працює
Анірбан,


1
  • Отримати відстань від верхньої частини даного елемента
  • Додайте висоту того самого даного елемента. Це покаже вам загальну кількість від верхньої частини екрану до кінця даного елемента.
  • Тоді все, що вам потрібно зробити, це відняти це від загальної висоти документа

    jQuery(function () {
        var documentHeight = jQuery(document).height();
        var element = jQuery('#you-element');
        var distanceFromBottom = documentHeight - (element.position().top + element.outerHeight(true));
        alert(distanceFromBottom)
    });
    

-1

Ви можете перевірити позицію div, використовуючи $(div).position()та перевірити, чи властивості лівого та верхнього полів менше 0:

if($(div).position().left < 0 && $(div).position().top < 0){
    alert("off screen");
}

2
Що робити, якщо div не є негативним за межами зору?
чувак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.