当元素完全在视图中时,使用 .each() 到 运行 分隔函数
Using .each() to run separate function when the element is totally in view
我在一次只为 class 的一个实例获取代码 运行 时遇到了一些麻烦。
我知道这段代码在使用只有一个实例的元素时有效,例如我以前使用过的 ID。但是,这次我尝试在不同时间(当每个元素都滚动时)多次使用相同的函数。
我也知道这很接近,它 运行s,并添加 class,只添加到所有实例,而不是一次一个,因为它滚动到视图中。
我可以看到自己 运行 绕着圈子试图解释这一点,所以这是我的代码,如果您需要帮助理解代码,请告诉我。我希望这只是我误解的一个简单概念。
(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>
感谢该代码段可能不起作用。
我删除了一些与当前问题无关的 CSS 并稍微简化了您的代码 (https://whosebug.com/help/minimal-reproducible-example)。这就是我最终得到的。将滚动事件绑定到 window
对象很重要,但要检查每个 .timeline-point
-divs 它们是否(完全)可见(对于我选择 "fully" 可见的演示,因为在这里更容易追踪)。 if(isInView(el,1)) $(el).addClass('open')
会在 isInView()
returns true
.
时将 class "open" 永久添加到 class 列表中
[[请注意,该代码在 Internet Explorer 中不会 运行,因为它不支持 ES6 箭头函数,但如果将它们更改为 "normal" 函数,它应该可以工作还有。]]
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()
函数稍微更改为 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));
我在一次只为 class 的一个实例获取代码 运行 时遇到了一些麻烦。
我知道这段代码在使用只有一个实例的元素时有效,例如我以前使用过的 ID。但是,这次我尝试在不同时间(当每个元素都滚动时)多次使用相同的函数。
我也知道这很接近,它 运行s,并添加 class,只添加到所有实例,而不是一次一个,因为它滚动到视图中。
我可以看到自己 运行 绕着圈子试图解释这一点,所以这是我的代码,如果您需要帮助理解代码,请告诉我。我希望这只是我误解的一个简单概念。
(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>
感谢该代码段可能不起作用。
我删除了一些与当前问题无关的 CSS 并稍微简化了您的代码 (https://whosebug.com/help/minimal-reproducible-example)。这就是我最终得到的。将滚动事件绑定到 window
对象很重要,但要检查每个 .timeline-point
-divs 它们是否(完全)可见(对于我选择 "fully" 可见的演示,因为在这里更容易追踪)。 if(isInView(el,1)) $(el).addClass('open')
会在 isInView()
returns true
.
[[请注意,该代码在 Internet Explorer 中不会 运行,因为它不支持 ES6 箭头函数,但如果将它们更改为 "normal" 函数,它应该可以工作还有。]]
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()
函数稍微更改为 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));