【问题标题】:Using .each() to run separate function when the element is totally in view当元素完全在视图中时,使用 .each() 运行单独的函数
【发布时间】:2020-01-31 20:56:10
【问题描述】:

我在让代码一次只运行一个类的实例时遇到了一些麻烦。

我知道这个代码在使用只有一个实例的元素时有效,例如我之前使用过的 ID。但是,这一次我尝试在不同的时间(滚动每个元素时)多次使用相同的功能。

我也知道这很接近,它运行并添加类,只添加到所有实例,而不是一次一个,因为它被滚动到视图中。

我可以看到自己绕着​​圈子试图解释这一点,所以这是我的代码,如果您需要帮助理解代码,请告诉我。我希望这只是一个我误解的简单概念。

(function($) {

    //CHECK SCROLLED INTO VIEW UTIL
    function Utils() {

    }

    Utils.prototype = {
        constructor: Utils,
        isElementInView: function (element, fullyInView) {
            var pageTop = $(window).scrollTop();
            var pageBottom = pageTop + $(window).height();
            var elementTop = $(element).offset().top;
            var elementBottom = elementTop + $(element).height();

            if (fullyInView === true) {
                return ((pageTop < elementTop) && (pageBottom > elementBottom));
            } else {
                return ((elementTop <= pageBottom) && (elementBottom >= pageTop));
            }
        }
    };

    var Utils = new Utils();
    //END CHECK SCROLLED INTO VIEW UTIL

    //USING THE ELEMENT IN VIEW UTIL
    //this function tells what to do do when the element is or isnt in view.
    //var inView = Utils.isElementInView(el, false); Where FALSE means the element doesnt need to be completely in view / TRUE would mean the element needs to be completely in view
    function IsEInView(el) {
    
        var inView = Utils.isElementInView(el, false);

        if(inView) {

            if (el.hasClass('open')) {
                //do nothing
            } else {
                el.addClass('open');
            }

        } else {
            //console.log('not in view');
        }

    };

    //Check to make sure the element you want to be sure is visible is present on the page
    var variableOfYourElement = $('.timeline-point');
    console.log(variableOfYourElement);

    //if it is on this page run the function that checks to see if it is partially or fully in view
    if( variableOfYourElement.length ) {

        variableOfYourElement.each(function(){

            el = $(this);

            //run function on page load
            IsEInView(el);

            //run function if the element scrolls into view
            $(window).scroll(function(){

                IsEInView(el);

            });

        })

    }
    //END USING THE ELEMENT IN VIEW UTIL

})(jQuery);
.massive-spacer {
    width: 100%;
    height: 1234px;
    background-color: pink;
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box!important;
    position: relative;
    word-wrap: break-word;
}

.section {
    width: 100%;
    height: auto;
    margin: 0 auto;
    position: relative;
    display: block;
}   
    .section-inner {
        width: 100%;
        max-width: 1248px;
        height: auto;
        margin: 0 auto;
        position: relative;

        display: -webkit-box;
        display: -ms-flexbox;
        display: -webkit-flex;
        display: flex;
        -webkit-flex-wrap: wrap;
        flex-wrap: wrap;

        flex-direction: row;
        align-items: stretch;
        justify-content: space-between;
    }

/* ------------------- */

.timeline {
    width: 100%;
    min-height: 600px;
    display: -webkit-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -webkit-flex-wrap: wrap;
    flex-wrap: wrap;

    flex-direction: row;
    align-items: center;
    justify-content: center;
}
.timeline-point {
    width: 100%;
    height: 400px;
    display: -webkit-box;
    display: -ms-flexbox;
    display: -webkit-flex;
    display: flex;
    -webkit-flex-wrap: wrap;
    flex-wrap: wrap;

    flex-direction: row;
    align-items: center;
    justify-content: center;
}
    .timeline-point.open {
        background-color: purple;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div class="massive-spacer"></div>

<div class="section about-history-section">
    <div class="section-inner">
        <div class="timeline">
            <div class="timeline-point">a</div>
            <div class="timeline-point">b</div>
            <div class="timeline-point">c</div>
            <div class="timeline-point">d</div>
            <div class="timeline-point">e</div>
            <div class="timeline-point">f</div>
        </div>
    </div>
</div>

<div class="massive-spacer"></div>

我很欣赏 sn-p 可能不起作用。

【问题讨论】:

    标签: jquery css each


    【解决方案1】:

    我删除了一些与当前问题无关的 CSS,并稍微简化了您的代码 (https://stackoverflow.com/help/minimal-reproducible-example)。这就是我最终的结果。将滚动事件绑定到 window 对象很重要,但要检查每个 .timeline-point-divs 是否(完全)可见(对于演示,我选择“完全”可见,因为它更容易跟踪这里)。只要isInView() 返回trueif(isInView(el,1)) $(el).addClass('open') 就会将“open”类永久添加到类列表中。

    [[请注意,代码不会在 Internet Explorer 中运行,因为它不支持 ES6 箭头函数,但如果您将它们更改为“普通”函数,它也应该可以在那里运行。]]

    function isInView(element, fullyInView) {
      var pageTop = $(window).scrollTop();
      var pageBottom = pageTop + $(window).height();
      var elementTop = $(element).offset().top;
      var elementBottom = elementTop + $(element).height();
      // use a ternary operator ( ? : ) here to apply one of two possible tests
      // and return result directly
      return ( fullyInView 
               ? pageTop < elementTop && pageBottom > elementBottom
               : elementTop <= pageBottom && elementBottom >= pageTop );
    };
    // bind scroll event to window object:
    $(window).scroll(()=>$('.timeline-point').each((i,el)=>{ // for each div do ...
      if(isInView(el,1)) $(el).addClass('open') 
    }));
    .massive-spacer {
        width: 100%;
        height: 50px;
        background-color: pink;
    }
    * { position: relative;}
    .timeline-point {
        width: 100%;
        height: 150px;
        text-align: center
    }
    .timeline-point.open {
        background-color: purple;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="massive-spacer"></div>
    
    <div class="section about-history-section">
    	<div class="section-inner">
    		<div class="timeline">
    			<div class="timeline-point">a</div>
    			<div class="timeline-point">b</div>
    			<div class="timeline-point">c</div>
    			<div class="timeline-point">d</div>
    			<div class="timeline-point">e</div>
    			<div class="timeline-point">f</div>
    		</div>
    	</div>
    </div>
    
    <div class="massive-spacer"></div>

    您可以通过将isInView()-function 稍微更改为setOpenClass(i,el) 来编写更短的代码,例如:

    function setOpenClass(i,el) {
      var pageTop = $(window).scrollTop();
      var pageBottom = pageTop + $(window).height();
      var elementTop = $(el).offset().top;
      var elementBottom = elementTop + $(el).height();
      if( true // = fullyInView 
         ? pageTop < elementTop && pageBottom > elementBottom
         : elementTop <= pageBottom && elementBottom >= pageTop) $(el).addClass('open')
    };
    // bind scroll event to window object:
    $(window).scroll(()=>$('.timeline-point').each(setOpenClass));
    

    【讨论】:

    • 粉碎了它,小伙子!我可以厚颜无耻地请你在申请后帮助我保持公开课。一旦它发生一次,我需要它保持与元素的连接。
    • 如果你更新 c 时可以通知我:我也喜欢在脸颊上加倍。您能否稍微评论一下代码,以便我可以按照您的逻辑进行操作,您已将我的代码压缩到大约 1/4 大小...#mindbent
    • 那是你给我的一些严肃的代码,伙计。万分感谢!如果您喜欢我的问题,请点赞:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 2013-12-10
    • 1970-01-01
    • 1970-01-01
    • 2016-07-31
    • 1970-01-01
    相关资源
    最近更新 更多