【问题标题】:Enable scrolling event when div is in viewport only once then reset when out of viewport当 div 仅在视口中时启用滚动事件,然后在视口外时重置
【发布时间】:2018-02-09 19:48:01
【问题描述】:

我试图在元素每次进入 Amplitude 视口时对其进行跟踪。现在,当一个元素滚动到视图中时,jQuery 会检测元素 id,如果它向上或向下滚动,并声明它是一个滚动事件。这些项目显示在 Amplitude admin 中。问题是当 div 在视口中时,每次鼠标滚动都会触发滚动事件。因此,当视口中的每个元素只需要一个事件时,它会创建大量事件。如何只触发一次事件,然后在它再次超出视口时将其重置?

     function isScrolledIntoView(elem) {

            // set offset by 10%
            var offSet = jQuery(window).height()*0.1;
            // offset scrolltop
            var docViewTop = jQuery(window).scrollTop() + offSet;
            // set window height area to 80% 
            var windowSize = jQuery(window).height()*0.8;

            var docViewBottom = docViewTop + windowSize;

            var elemTop = jQuery(elem).offset().top;

            var elemBottom = elemTop + jQuery(elem).height();


            return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));


        }
        var lastScrollTop = 0;
        jQuery(window).scroll(function (event) {

                // detects scroll direction.
                var st = jQuery(this).scrollTop();
                   if (st > lastScrollTop){
                     var action = 'ScrollDown';
                   } else {
                      var action = 'ScrollUp';
                   }
                   lastScrollTop = st;



                jQuery('.trackScrolling').each(function () {

                    // get element ID
                   var elementID = jQuery(this).attr("id");

                    var ScrollEvents = 'ScrollEvents';  

                  // if in viewport fire event
                    if (isScrolledIntoView(this) === true) {


                      gu_event(ScrollEvents, action, elementID);


                    } 


                });

        });

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    您需要为每个元素创建一个布尔标志以检查它是否已经在视口中并添加另一个if 条件检查,如下所示:

    var elements = [];
    var lastScrollTop = 0;
    
    jQuery('.trackScrolling').each(function () {
        elements.push({
            "elem": this,
            "id": jQuery(this).attr("id")),
            "inView": false
        });
    });
    
    function isScrolledIntoView(elem) {
        // set offset by 10%
        var offSet = jQuery(window).height()*0.1;
    
        // offset scrolltop
        var docViewTop = jQuery(window).scrollTop() + offSet;
    
        // set window height area to 80% 
        var windowSize = jQuery(window).height()*0.8;
    
        var docViewBottom = docViewTop + windowSize;
        var elemTop = jQuery(elem).offset().top;
        var elemBottom = elemTop + jQuery(elem).height();
    
        return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop));
    }
    
    jQuery(window).scroll(function (event) {
        var action;
    
        // detects scroll direction.
        var st = jQuery(this).scrollTop();
    
        if (st > lastScrollTop){
           action = 'ScrollDown';
        } else {
           action = 'ScrollUp';
        }
    
        lastScrollTop = st;
    
        for (var i = 0; i < elements.length; i++) {
            var ScrollEvents = 'ScrollEvents';
    
            if (elements[i].inView === true && isScrolledIntoView(elements[i].elem) === true) {
    
                // do nothing in this case...
                console.log('Element ' + elements[i].id + ' is already in view!');
    
            } else if (isScrolledIntoView(elements[i].elem) === true) {
    
                // set the flag in this case and send the event
                elements[i].inView = true;
                gu_event(ScrollEvents, action, elements[i].id);
    
            } else if (isScrolledIntoView(elements[i].elem) === false) {
    
                // reset the flag in this case
                elements[i].inView = false;
            }
        }
    });
    

    与您的 scroll 函数不断查找所有 .trackScrolling 元素不同,我预先存储了对它们的引用 - 每个的 ID 以及它是否在视口中都存储在一个对象中。

    【讨论】:

    • 它似乎仍然在视口中的每个像素滚动上触发事件。我已经添加了InView = false;在 gu_event 之后。那也没用。
    • Oof... 抱歉,标志变量应该超出此函数的范围(就像您的 lastScrollTop 变量一样)。否则,当函数运行时,它总是重置为 false。但是你需要为每个元素有一个单独的变量,所以你需要一个数组或元素的引用对象。
    • 我已经更新了我的答案以反映这一点 - 如果有任何不清楚的地方请告诉我。
    • 谢谢!!我收到“未定义 elementID”错误。它看不到带有 trackScrolling 类的 div 的 ID。将 console.log('in view') 用作显示事件仅触发一次的方法吗?我正在本地工作,而不是在 Amplitude。
    • 抱歉,变量名有错别字。现在再试一次 - 是的,我将控制台日志添加到显示当前元素 ID 的第一个条件中。
    猜你喜欢
    • 2017-08-23
    • 2014-06-04
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多