简体   繁体   English

如果滚动时可见div,则对主体进行动画处理并更改其背景颜色

[英]Animate and change background-color of body if a div is visible while scrolling

I'm trying to change the background-color of my body with jQuery, when a specific div (in my example the red one) is visible while scrolling. 当尝试在滚动时看到特定的div(在我的示例中为红色)时,我正在尝试使用jQuery更改bodybackground-color If the div is not visible, the background-color should change again with an animation. 如果div不可见,则背景色应通过动画再次更改。 I tried follow, but it's not working. 我尝试了跟踪,但是没有用。 Here's also a codepen snippet: https://codepen.io/STWebtastic/pen/qpKdeo 这也是一个Codepen代码段: https ://codepen.io/STWebtastic/pen/qpKdeo

 $(window).scroll(function(){ $('.m-box--red').each(function(){ if(isScrolledIntoView($(this)) ){ $("html body").animate({ backgroundColor: "red" }, 300); console.log('hello'); } else{ $("html body").animate({ backgroundColor: "white" }, 300); console.log('hello'); } }); }); function isScrolledIntoView(elem){ var $elem = $(elem); var $window = $(window); var docViewTop = $window.scrollTop(); var docViewBottom = docViewTop + $window.height(); var elemTop = $elem.offset().top; var elemBottom = elemTop + $elem.height(); return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); } 
 body { box-sizing: border-box; margin: 0; } .m-box { display: flex; align-items: center; padding: 10px; background-color: #75989F; margin-bottom: 100px; cursor: pointer; color: white; transition: background-color 0.3s; height: 300px; } .m-box--second { background-color: #68808E; } .m-box--third { background-color: #CDC2AA; color: gray; } .m-box--red { background-color: #D29B8E; border: 1px solid lightgray; } .m-box__text { font-size: 45px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> <div class="m-box m-box--second"> <p class="m-box__text">Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Nulla porttitor accumsan tincidunt. Sed porttitor lectus nibh. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--red"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--third"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> 

One problem could be this : 一个问题可能是这样的:

jQuery animate backgroundColor jQuery动画backgroundColor

And the other problem is that you loop over all the div so the body background will get the color of the condition which is in the last item of the loop. 另一个问题是,您遍历了所有div,因此主体背景将获得条件的颜色,该条件位于循环的最后一项中。 So in your case, always white. 因此,就您而言,始终为白色。

So i think you could just addClass with a transition on the background property and only test the red div. 因此,我认为您可以在background属性上添加带有过渡的addClass并仅测试红色div。

Working codepen : 工作码笔:

https://codepen.io/Alvan/pen/rpKLjY?editors=1111 https://codepen.io/Alvan/pen/rpKLjY?editors=1111

 $(window).scroll(function(){ $('.m-box--red').each(function(){ if(isScrolledIntoView($(this)) ){ $("body").addClass('red'); } else{ $("body").removeClass('red'); } }); }); function isScrolledIntoView(elem){ var $elem = $(elem); var $window = $(window); var docViewTop = $window.scrollTop(); var docViewBottom = docViewTop + $window.height(); var elemTop = $elem.offset().top; var elemBottom = elemTop + $elem.height(); return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); } 
 body { box-sizing: border-box; margin: 0; background: white; transition: background .3s; } body.red { background: red; } .m-box { display: flex; align-items: center; padding: 10px; background-color: #75989F; margin-bottom: 100px; cursor: pointer; color: white; transition: background-color 0.3s; height: 150px; } .m-box:hover { background-color: lighten(#75989F, 10); } .m-box--second { background-color: #68808E; } .m-box--second hover { background-color: lighten(#68808E, 10); } .m-box--third { background-color: #CDC2AA; color: gray; } .m-box--third:hover { background-color: lighten(#CDC2AA, 10); } .m-box--red { background-color: #D29B8E; border: 1px solid lightgray; } .m-box--red :hover { background-color: lighten(#D29B8E, 10); } .m-box__text { font-size: 10px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> <div class="m-box m-box--second"> <p class="m-box__text">Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Nulla porttitor accumsan tincidunt. Sed porttitor lectus nibh. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--red"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--third"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> 

If you want the function to work when the top appears at the screen until the bottom disappear from the screen change the condition in function isScrolledIntoView to 如果希望该功能在屏幕顶部出现直到屏幕底部消失时起作用,则将function isScrolledIntoView的条件更改为

if(elemTop <= docViewBottom && elemBottom >= docViewTop) {
    return true;
}

 $(window).scroll(function(){ $('.m-box--red').each(function(){ if(isScrolledIntoView($(this)) ){ $("body").addClass('red'); } else{ $("body").removeClass('red'); } }); }); function isScrolledIntoView(elem){ var $elem = $(elem); var $window = $(window); var docViewTop = $window.scrollTop(); var docViewBottom = docViewTop + $window.height(); var elemTop = $elem.offset().top; var elemBottom = elemTop + $elem.height(); if(elemTop <= docViewBottom && elemBottom >= docViewTop) { return true; } } 
 body { box-sizing: border-box; margin: 0; background: white; transition: background .3s; } body.red { background: red; } .m-box { display: flex; align-items: center; padding: 10px; background-color: #75989F; margin-bottom: 100px; cursor: pointer; color: white; transition: background-color 0.3s; height: 150px; } .m-box:hover { background-color: lighten(#75989F, 10); } .m-box--second { background-color: #68808E; } .m-box--second hover { background-color: lighten(#68808E, 10); } .m-box--third { background-color: #CDC2AA; color: gray; } .m-box--third:hover { background-color: lighten(#CDC2AA, 10); } .m-box--red { background-color: #D29B8E; border: 1px solid lightgray; } .m-box--red :hover { background-color: lighten(#D29B8E, 10); } .m-box__text { font-size: 10px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> <div class="m-box m-box--second"> <p class="m-box__text">Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Nulla porttitor accumsan tincidunt. Sed porttitor lectus nibh. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--red"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--third"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> 

You should use jQuery's .is and :visible selectors to do this: 您应该使用jQuery的.is:visible选择器来执行此操作:

const $scrollTarget = $(".m-box");
const $body = $("body");
const $window = $(window);

$window.on("scroll", function() {
    return $scrollTarget.is(":visible") ? $body.addClass("element-visible-class") : $body.removeClass("element-visible-class");
});

Where element-visible-class is the class you want to apply when the element is visible. 其中element-visible-class是元素可见时要应用的类。

I made some changes to your code, but I think this is the solution you are looking for: 我对您的代码进行了一些更改,但是我认为这是您正在寻找的解决方案:

 $(window).scroll(function() { var hT = $('.m-box--red').offset().top, hH = $('.m-box--red').outerHeight(), wH = $(window).height(), wS = $(this).scrollTop(); if (wS >= (hT+hH) || wS < (hT+hH-wH)){ $("body").css("background-color", "white"); } else if (wS > (hT+hH-wH)) { $("body").css("background-color", "red"); } }); 
 body { box-sizing: border-box; margin: 0; transition: background-color .5s; } .m-box { display: flex; align-items: center; padding: 10px; background-color: #75989F; margin-bottom: 100px; cursor: pointer; color: white; transition: background-color 0.3s; height: 300px; } .m-box:hover { background-color: #93aeb4; } .m-box--second { background-color: #68808E; } .m-box--second:hover { background-color: #8499a5; } .m-box--third { background-color: #CDC2AA; color: gray; } .m-box--third:hover { background-color: #e0d9ca; } .m-box--red { background-color: #D29B8E; border: 1px solid lightgray; } .m-box--red:hover { background-color: #e1bbb2; } .m-box__text { font-size: 45px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> <div class="m-box m-box--second"> <p class="m-box__text">Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Nulla porttitor accumsan tincidunt. Sed porttitor lectus nibh. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--red"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--third"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> 

You just have to add 您只需要添加

transition: background-color .5s;

to the body in your css. 放在您的CSS身上。

according to jquery doc ( http://api.jquery.com/animate/ ) : 根据jquery doc( http://api.jquery.com/animate/ ):

All animated properties should be animated to a single numeric value, except as noted below; 除非另有说明,否则所有动画属性都应设置为单个数值。 most properties that are non-numeric cannot be animated using basic jQuery functionality (For example, width, height, or left can be animated but background-color cannot be, unless the jQuery.Color plugin is used). 大多数非数字属性不能使用基本的jQuery功能进行动画处理(例如,可以对width,height或left进行动画处理,但不能对background-color进行动画处理,除非使用jQuery.Color插件)。

If you don't want to use this plugin, you can achieve this by completing your css and adding a class to your body when you need 如果您不想使用此插件,则可以通过完成CSS并在需要时向您的身体添加类来实现此目的

 $(window).scroll(function(){ $('.m-box--red').each(function(){ // change the selector cause you only need this on m-box--red $("html body").toggleClass("red",isScrolledIntoView($(this))); // check if the condition is true then add class red, else remove it }); }); function isScrolledIntoView(elem){ var $elem = $(elem); var $window = $(window); var docViewTop = $window.scrollTop(); // also chnage this var docViewBottom = docViewTop + $("body").height(); var elemTop = $elem.offset().top; var elemBottom = elemTop + $elem.height(); return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); } 
 body { box-sizing: border-box; margin: 0; transition: background-color 0.3s; } body.red{ background-color:red; } .m-box { display: flex; align-items: center; padding: 10px; background-color: #75989F; margin-bottom: 100px; cursor: pointer; color: white; transition: background-color 0.3s; height: 300px; } .m-box--second { background-color: #68808E; } .m-box--third { background-color: #CDC2AA; color: gray; } .m-box--red { background-color: #D29B8E; border: 1px solid lightgray; } .m-box__text { font-size: 45px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> <div class="m-box m-box--second"> <p class="m-box__text">Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Nulla porttitor accumsan tincidunt. Sed porttitor lectus nibh. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--red"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--third"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> 

I would suggest a few changes to better optimize your code (and fix it at the same time!): 我建议进行一些更改,以更好地优化您的代码(并同时修复它!):

  1. Make css animate the background color for you, as that is what css if for. 使css为您设置背景颜色的动画,这就是css的目的。
  2. Move a lot of the processing you're currently doing inside the scroll event handler, outside to minimize what needs to be done on that event. 移动很多你目前在做滚动事件处理程序内部的处理中, 以减少需要对这一事件做了什么。 This will prevent stutterly scrolling, or "jank". 这样可以防止滚动滚动或“颠簸”。

Number one can be done by simply adding this to your css: 只需将其添加到您的CSS中就可以完成第一件事:

body {
  transition: background-color .3s;
}

and then changing your javascript from using the animate() jquery function to simply changing the css property like so: 然后将您的javascript从使用animate() jquery函数更改为简单地更改css属性,如下所示:

$('body').css('background-color','red');

The css transition property will then natively handle the color transition for you. 然后,css transition属性将为您本地处理颜色过渡。 In fact, an even better way to do it would be to have the javascript simply add/remove a class and have the css handle what that class means for the styling. 实际上,一种更好的方法是让javascript简单地添加/删除一个类,并让CSS处理该类对样式的含义。 Then you can use css to control what styles are applied to this special state of the body tag -- which is where your styles should be. 然后,您可以使用css来控制将什么样式应用于此body标签的特殊状态-这就是样式的位置。

Here is my rewrite of your code working towards these improvements (you need to view the snippet as full screen in order for the effect to work): 这是我为实现这些改进而编写的代码(为了使效果正常工作,您需要全屏查看代码段):

 (function(){ var $window = $(window); var $elem = $('.m-box--red'); var elemTop = $elem.offset().top; var elemBottom = elemTop + $elem.height(); $(window).scroll(function(){ if( isScrolledIntoView( $elem )) $('body').addClass('js-active'); else $('body').removeClass('js-active'); }); function isScrolledIntoView($elem){ var docViewTop = $window.scrollTop(); var docViewBottom = docViewTop + $window.height(); return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); } })(); 
 body { box-sizing: border-box; margin: 0; transition: background-color .3s; } body.js-active { background-color: red; } .m-box { display: flex; align-items: center; padding: 10px; background-color: #75989F; margin-bottom: 100px; cursor: pointer; color: white; transition: background-color 0.3s; height: 300px; } .m-box:hover { background-color: #93aeb4; } .m-box--second { background-color: #68808E; } .m-box--second:hover { background-color: #8499a5; } .m-box--third { background-color: #CDC2AA; color: gray; } .m-box--third:hover { background-color: #e0d9ca; } .m-box--red { background-color: #D29B8E; border: 1px solid lightgray; } .m-box--red:hover { background-color: #e1bbb2; } .m-box__text { font-size: 45px; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> <div class="m-box m-box--second"> <p class="m-box__text">Curabitur non nulla sit amet nisl tempus convallis quis ac lectus. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Nulla porttitor accumsan tincidunt. Sed porttitor lectus nibh. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--red"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box m-box--third"> <p class="m-box__text">Mauris blandit aliquet elit, eget tincidunt nibh pulvinar a. Donec sollicitudin molestie malesuada. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi.</p> </div> <div class="m-box"> <p class="m-box__text">Quisque velit nisi, pretium ut lacinia in, elementum id enim.</p> </div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM