Как реализовать событие onVisible в Javascript? - PullRequest
21 голосов
/ 27 сентября 2010

Есть ли какая-либо техника или набор техник, которые можно использовать для реализации того, что, по сути, было бы onVisible 'событием' в JavaScript?

Я бы хотел, чтобы мой JavaScript обнаруживал, когда элемент ввеб-страница, такая как текстовый абзац или изображение, становится видимой в окне браузера, когда пользователь прокручивает страницу вниз.Я также хотел бы, чтобы соответствующее событие «onNotVisible» запускалось, когда элемент, который когда-то был виден в окне браузера, больше не виден.

Если это не может быть легко реализовано в JavaScript, есть ли браузер?конкретные события, которые могут обеспечить такую ​​же функциональность?

Ответы [ 3 ]

8 голосов
/ 27 сентября 2010

Я должен был попробовать это сам, и вот что я придумал:

<!DOCTYPE html>
<html>
<head>
<script>

var EventListener = function(element, callback) {
    this._el = element;
    this._cb = callback;
    this._at = false;
    this._hasBeenVisible = false;
    this._hasBeenInvisible = true;
    var  _me = this;

    window.onscroll = function() {
        for (q in EventListener.queue.onvisible) {
            EventListener.queue.onvisible[q].call();
        }
        for (q in EventListener.queue.oninvisible) {
            EventListener.queue.oninvisible[q].call();
        }
    };

    return {
        onvisible: function() {
            EventListener.queue.onvisible.push(function() {
                if (!_me._at && _me._hasBeenInvisible && (window.pageYOffset + window.innerHeight) > _me._el.offsetTop && window.pageYOffset < (_me._el.offsetTop + _me._el.scrollHeight)) {
                    _me._cb.call();
                    _me._at = true;
                    _me._hasBeenVisible = true;
                }
            });
            EventListener.queue.oninvisible.push(function() {
                if (_me._hasBeenVisible && ((window.pageYOffset + window.innerHeight) < _me._el.offsetTop || window.pageYOffset > (_me._el.offsetTop + _me._el.scrollHeight))) {
                    _me._hasBeenInvisible = true;
                    _me._hasBeenVisible   = false;
                    _me._at = false;
                }
            });
        },
        oninvisible: function() {
            EventListener.queue.oninvisible.push(function() {
                if (!_me._at && _me._hasBeenVisible && ((window.pageYOffset + window.innerHeight) < _me._el.offsetTop || window.pageYOffset > (_me._el.offsetTop + _me._el.scrollHeight))) {
                    _me._cb.call();
                    _me._at = true;
                    _me._hasBeenInvisible = true;
                }
            });
            EventListener.queue.onvisible.push(function() {
                if (_me._hasBeenInvisible && (window.pageYOffset + window.innerHeight) > _me._el.offsetTop && window.pageYOffset < (_me._el.offsetTop + _me._el.scrollHeight)) {
                    _me._hasBeenVisible = true;
                    _me._hasBeenInvisible = false;
                    _me._at = false;
                }
            });
        }
    };
}
EventListener.queue = {
    onvisible:   [],
    oninvisible: []
};

function addListener(element, event, fn) {
    if (typeof element == 'string')
        element = document.getElementById(element);

    var listener = new EventListener(element, fn);

    if (listener['on' + event.toLowerCase()])
        return listener['on' + event.toLowerCase()].call();
}

window.onload = function() {
    addListener('event-element', 'visible', function() {
        alert("Element One Visible!");
    });
    addListener('event-element', 'invisible', function() {
        alert("Element One Invisible!");
    });
    addListener('event2-element', 'visible', function() {
        alert("Element Two Visible!");
    });
    addListener('event2-element', 'invisible', function() {
        alert("Element Two Invisible");
    });
}

</script>
</head>
<body>

<h1>Hey!</h1>

<div style="height: 1500px;">
Please scroll down some pixels.
</div>

<p id="event-element">
    This element should cast an event 'onvisible' and 'oninvisible'.
</p>

<div style="height: 1000px;">

</div>

<p id="event2-element">
    Another one!
</p>


</body>
</html>

Проверено в:

  • FireFox 3.6 (работает)
  • Chrome 6.0.472 (работает)
  • Опера 10,62 (работает)
  • Safari 4 (работает в очень глючной и раздражает, не используйте всплывающие окна, если ты попробуй это здесь!)

( Код также доступен на PasteBin )

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

5 голосов
/ 27 сентября 2010

Вам нужно настроить прослушиватель событий для события onscroll документа или окна.Затем вы должны измерить видимую в данный момент область, добавив clientHeight в scrollTop, а затем проверить, находится ли выбранный вами элемент в этой области.Примерно так:

myElem=document.getElementById('some_id');
scrollOffset=document.getElementsByTagName('html')[0].scrollTop;
visibleHeight=document.getElementsByTagName('html')[0].clientHeight;
if(myElem.offsetTop>=scrollOffset && myElem.offsetTop<=scrollOffset+visibleHeight){
    // element is in visible area
}

Если это так, вы устанавливаете какой-то флаг в своем коде.

Хотя вы, вероятно, столкнетесь с несовместимостью браузеров.Так что лучше используйте библиотеку.

4 голосов
/ 13 марта 2013

Один из ответов в вопросе , связанном выше @edbond, дает указатель на плагин jQuery появляются .Этот плагин позволяет вам прикреплять обратные вызовы appear и disappear к элементу, который вызывается при прокрутке элемента в поле обзора и вне его, что звучит как то, что вы ищете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...