最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

html - How to implement an 'onVisible' event in JavaScript? - Stack Overflow

programmeradmin1浏览0评论

Is there any technique or set of techniques that can be used to implement what, in effect, would be an onVisible 'event' in JavaScript?

I would like my JavaScript to detect when an element in a web page, such as a paragraph of text, or an image, becomes visible in a browser window as a user scrolls down a page. I would also like a corresponding 'event', onNotVisible, to fire when an element that was once visible in the browser window can no longer be seen.

If it cannot be easily implemented in JavaScript, are there any browser specific events that can provide the same functionality?

Is there any technique or set of techniques that can be used to implement what, in effect, would be an onVisible 'event' in JavaScript?

I would like my JavaScript to detect when an element in a web page, such as a paragraph of text, or an image, becomes visible in a browser window as a user scrolls down a page. I would also like a corresponding 'event', onNotVisible, to fire when an element that was once visible in the browser window can no longer be seen.

If it cannot be easily implemented in JavaScript, are there any browser specific events that can provide the same functionality?

Share Improve this question edited Aug 25, 2022 at 20:02 Brian Tompsett - 汤莱恩 5,88372 gold badges61 silver badges133 bronze badges asked Sep 27, 2010 at 17:30 RobertGRobertG 2811 gold badge3 silver badges3 bronze badges 2
  • may be this might help you stackoverflow.com/questions/399867/custom-events-in-jquery – user372551 Commented Sep 27, 2010 at 17:44
  • 2 see stackoverflow.com/questions/487073/… – edbond Commented Sep 27, 2010 at 19:43
Add a comment  | 

3 Answers 3

Reset to default 10

I had to try this myself, and this is what I came up with:

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

Tested in:

  • FireFox 3.6 (works)
  • Chrome 6.0.472 (works)
  • Opera 10.62 (works)
  • Safari 4 (Works in a very buggy and irritating way, don't use popups if you try it here!)

(The code is also available on PasteBin)

The above code is not optimized in any way, I just started writing and ended when it worked. Preferrably you would probably want to use only one queue, refactor some code and make it more generic. Provided as is.

You'd have to set up an event listener for the document's or window's onscroll event. Then you'd measure the currently visible area by adding the clientHeight to scrollTop, and then you check if your element of choice is within that area. Something like this

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
}

If that's the case you set some flag somewhere in your code.

You're likely to run into browser incompatibilities there though. So better use some library.

One of the answers in the question linked above by @edbond gives a pointer to the jQuery appear plugin. This plugin allows you to attach appear and disappear callbacks to an element that are called as the element scrolls into and out of view, which sounds like exactly what you are looking for.

发布评论

评论列表(0)

  1. 暂无评论