2012-01-17 4 views
65

Мне нужно проверить с помощью jQuery, если элемент DIV не падает с экрана. Элементы видны и отображаются в соответствии атрибутов CSS, но они могут быть преднамеренно размещены вне экрана с помощью:Как проверить, является ли элемент вне экрана

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

Я не мог использовать :visible селектор JQuery как элемент имеет ненулевую высоту и ширину.

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

+0

Я дал ответ на этот вопрос, а также на этом «дубликата» вопрос: http://stackoverflow.com/ вопросы/5353934/check-if-element-is-visible-on-screen/5354536 # 5354536 – Tokimon

ответ

101

Зависит от того, что ваше определение «закадровый» есть. Это в пределах области просмотра или в пределах определенных границ вашей страницы?

Использование Element.getBoundingClientRect() вы можете легко обнаружить, является ли ваш элемент в пределах boundries вашего видового экрана (т.е. на экране или закадровым):

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'); 
+1

Мне это понравилось, но оно ломается, если ваш элемент находится внутри прокручиваемого контейнера. Элемент внизу DIV с двумя экранами всегда будет «вне экрана», так как высота окна меньше, чем offsetTop элемента. – Coderer

+0

@scurker Я не мог заставить это работать. Вот мой вопрос SO (с jsFiddle) о проблеме: http://stackoverflow.com/questions/26004098/extend-jquery-to-create-custom-filter-re-element-outside-viewport – crashwap

+0

Я ошибаюсь здесь, чтобы думаете, что это не будет, если el позиционирует родительский (абсолютный или относительный) перед телом? –

-1

Вы можете проверить положение DIV с помощью $(div).position() и проверить, если левый и верхний свойства полей меньше, чем 0:

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

Что делать, если div не отрицателен вне поля зрения? – dude

16

Существует jQuery plugin here, который позволяет пользователям проверять, попадает ли элемент в видимое окно просмотра браузера, принимая во внимание положение прокрутки браузеров.

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

Вы также можете проверить для частичной видимости:

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

Один недостаток заключается в том, что он работает только с вертикальным позиционированием/прокруткой, хотя он должен быть достаточно легким, чтобы добавить горизонтальное позиционирование в смеси.

+0

Это ОЧЕНЬ легкий плагин. Я смог получить фиксированную навигационную панель для прокрутки вверх и оперативно реагировать в течение нескольких минут после ее добавления. Отличное предложение. – Nappstir

+0

Этот плагин очень легкий и довольно прост в применении. Решил проблему, которую я имел с подменю. –

3

Я создал a small plugin that does this, и она имеет некоторые гибкие возможности (он также работает при изменении размера окна браузера).

+0

Как удалить класс 'right-edge'? на этом тестовом сайте [link] http://archeo.ecrc.pl/ element '.sub-menu', после применения класса' right-edge' он не удаляется после изменения размера окна браузера. – Daniel

+0

@ Даниэль Извините за безумно поздний ответ. Но теперь это исправлено :) –

7

Нет необходимости в плагине, чтобы проверить, находится ли внешний порт.

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

Это будет работать, если вы использовали '$ (this) .offset' вместо' $ this.position'. Сейчас это просто вычисление расстояния от родителя, которое может быть div, который отлично его обертывает. –

1

Ну ... Я нашел некоторые проблемы в каждом предлагаемом решении здесь.

  • Вы должны быть в состоянии выбрать, если вы хотите весь элемент быть на экране или только любой его части
  • Предлагаемые решения терпит неудачу, если элемент выше/шире окна и своего рода обложки окно браузера.

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

Я использую getBoundingClientRect метод, который возвращает позицию элемента относительно окна просмотра поэтому мне не нужно заботиться о положении прокрутки

Useage:

$(".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); 
}; 
+0

Я получаю make_footer_down.js: 8 Uncaught TypeError: Невозможно прочитать свойство 'getBoundingClientRect' неопределенного при попытке использовать функции ur там. – Lurr

+0

Привет, Lurr ... Я пытался с $ ("# divId"). IsOnScreen (true); где «divId» был вне экрана, и он вернул мне «ложь»; поэтому я чувствую, что он работает – Anirban

0
  • Получить расстояние от вершины данного элемента
  • Добавьте высоту того же заданного элемента. Это покажет вам общее число от верхней части экрана до конца данного элемента.
  • Тогда все, что вам нужно сделать, это вычесть, что из общей высоты документа

    jQuery(function() { 
        var documentHeight = jQuery(document).height(); 
        var element = jQuery('#you-element'); 
        var distanceFromBottom = documentHeight - (element.position().top + element.outerHeight(true)); 
        alert(distanceFromBottom) 
    }); 
    
Смежные вопросы