Событие Fire Javascript, когда DIV находится в представлении

Возможно ли запустить конкретное событие javascript, когда на странице появится страница DIV?

Скажем, у меня очень большая страница, например 2500x2500, и у меня есть 40x40 div, который сидит в позиции 1980x1250. Div не обязательно находится в ручном режиме, он может быть там из-за того, что контент его нажал. Теперь, можно ли запустить функцию, когда пользователь прокручивается до точки, где div становится видимым?

Ответ 1

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

Вот минимальный пример.

<div id="importantdiv">hello</div>

<script type="text/javascript">
    function VisibilityMonitor(element, showfn, hidefn) {
        var isshown= false;
        function check() {
            if (rectsIntersect(getPageRect(), getElementRect(element)) !== isshown) {
                isshown= !isshown;
                isshown? showfn() : hidefn();
            }
        };
        window.onscroll=window.onresize= check;
        check();
    }

    function getPageRect() {
        var isquirks= document.compatMode!=='BackCompat';
        var page= isquirks? document.documentElement : document.body;
        var x= page.scrollLeft;
        var y= page.scrollTop;
        var w= 'innerWidth' in window? window.innerWidth : page.clientWidth;
        var h= 'innerHeight' in window? window.innerHeight : page.clientHeight;
        return [x, y, x+w, y+h];
    }

    function getElementRect(element) {
        var x= 0, y= 0;
        var w= element.offsetWidth, h= element.offsetHeight;
        while (element.offsetParent!==null) {
            x+= element.offsetLeft;
            y+= element.offsetTop;
            element= element.offsetParent;
        }
        return [x, y, x+w, y+h];
    }

    function rectsIntersect(a, b) {
        return a[0]<b[2] && a[2]>b[0] && a[1]<b[3] && a[3]>b[1];
    }

    VisibilityMonitor(
        document.getElementById('importantdiv'),
        function() {
            alert('div in view!');
        },
        function() {
            alert('div gone away!');
        }
    );
</script>

Вы можете улучшить это:

  • чтобы он поймал onscroll всех предков, которые имеют overflow scroll или auto и корректируют верхние/левые координаты для своих положений прокрутки
  • обнаружение overflow scroll, auto и hidden обрезки, поместив div вне экрана
  • с помощью addEventListener/attachEvent, чтобы позволить нескольким VisibilityMonitors и другим вещам использовать события изменения размера/прокрутки
  • некоторые совместимые хаки с getElementRect, чтобы сделать координаты более точными в некоторых случаях, а некоторые события отключаются, чтобы избежать утечек памяти IE6-7, если вам действительно нужно.

Ответ 2

Здесь пример запуска с использованием jQuery:

<html>
<head><title>In View</title></head>
<body>
    <div style="text-align:center; font-size:larger" id="top"></div>
    <fieldset style="text-align:center; font-size:larger" id="middle">
        <legend id="msg"></legend>
        <div>&nbsp;</div>
        <div id="findme">Here I am!!!</div>
    </fieldset>
    <div style="text-align:center; font-size:larger" id="bottom"></div>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js" type="text/javascript"></script>

<script type="text/javascript">
    var $findme = $('#findme'),
        $msg = $('#msg');

    function Scrolled() {
        var findmeOffset = $findme.offset(),
            findmeTop = findmeOffset.top,
            scrollTop = $(document).scrollTop(),
            visibleBottom = window.innerHeight;

        if (findmeTop < scrollTop + visibleBottom) {
            $msg.text('findme is visible');
        }
        else {
            $msg.text('findme is NOT visible');
        }
    }

    function Setup() {
        var $top = $('#top'),
            $bottom = $('#bottom');

        $top.height(500);
        $bottom.height(500);

        $(window).scroll(function() {
            Scrolled();
        });
    }

    $(document).ready(function() {
        Setup();

    });
</script>
</body>
</html>

Он уведомляется только после того, как div появится в нижней части. Этот пример не уведомляет, когда div прокручивается сверху.