当DIV在视图中时触发Javascript事件

Rus*_*rry 10 javascript javascript-events

当某个DIV进入页面时,是否可以触发特定的javascript事件?

比方说,我有一个非常大的页面,比如2500x2500,我有一个位于1980x1250位置的40x40 div.div不一定是手动定位的,它可能存在,因为内容将其推到那里.现在,当用户滚动到div可见的点时,是否可以运行一个函数?

bob*_*nce 10

不是自动的.您必须通过比较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>
Run Code Online (Sandbox Code Playgroud)

您可以通过以下方式改进:

  • 让它捕获onscroll所有拥有overflow scrollauto调整顶部/左侧坐标的祖先的滚动位置
  • 检测overflow scroll,autohidden裁剪把DIV离屏
  • 使用addEventListener/ attachEvent允许使用调整大小/滚动事件的多个VisibilityMonitors和其他内容
  • getElementRect在某些情况下,一些兼容性攻击可以使协议更准确,如果你真的需要,有些事件可以解除绑定以避免IE6-7内存泄漏.


Tel*_*iRE 6

这是 2022 年理想的解决方案。当前的最佳答案仅允许您观察一项,并且存在性能问题,因为每次页面滚动时都会触发多次。

var observer = new IntersectionObserver(function(entries) {
    if(entries[0].isIntersecting === true) {
        console.log('Item has just APPEARED!');
    } else {
        console.log('Item has just DISAPPEARED!');
    }
}, { threshold: [0] });

observer.observe(document.querySelector("#DIV-TO-OBSERVE"));
Run Code Online (Sandbox Code Playgroud)

一旦该项目部分显示在屏幕上,就会触发此操作。将阈值更改为 1 将要求该项目完全显示在屏幕上(因此,如果该项目大于视口,它将永远不会触发)。您可以设置介于 0.25 之间的值,以便在至少 1/4 的项目处于视图中时触发。