Change color when user scroll down enough and then come back

I have several divs arranged vertically one on top of the other, which I will call panels from here. Each panel has the width and height of the viewport. All panels have the same background color. Initially, this color is black.

Each other panel is empty and acts as a gap between panels that actually have content. The order is as follows:

  • Content
  • No content
  • Content
  • No content
  • Content

What I want to do is to make sure that when the user scrolls down enough so that the contents of the panel do not appear, the color should change from black to white. Then, when they scroll far enough so that the second panel with the content does not appear, it should change.

This is the part that I cannot understand. So far I have a working demo with my code:

$(document).scroll(function() { var viewportHeight = $("html").outerHeight(); var currentY = $(document).scrollTop(); if (currentY % viewportHeight != 0) { lighten(); } else { darken(); } }); function darken() { $("body").css("background-color", "black"); $(".panel.content").css("color", "white"); } function lighten() { $("body").css("background-color", "white"); $(".panel.content").css("color", "black"); } 
 html, body, .panel { width: 100%; height: 100%; } body { background-color: black; overflow-y: visible; overflow-x: hidden; transition: background-color 500ms linear; } .panel { border: 2px solid red; } .content { color: white; text-align: center; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> <body> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> </body> 

As you can see, my code is the way from achieving the desired result. Not only the wrong order, the main problem is that it only starts when the user is in the exact Y to change.

The order should be:

  • The black
  • White
  • White
  • The black
  • The black
  • White
  • White
  • The black
  • The black

and etc.

How to do it?

+5
source share
7 answers

Here is my solution. I am sure that this is the order you need.

 (function() { var lastfunc = darken; $(document).scroll(function() { var y = $(document).scrollTop(); var x = $("html").outerHeight(); var func = (Math.floor(((y + x) / (2 * x))) % 2) ? lighten : darken; if (func !== lastfunc) { lastfunc = func; func(); } }); })(); 

This does the following:

  • Create a lastfunc variable to track the last thing we called.
  • Get user Y and viewport height.
  • Use evil factorized math to get a bool that decides which of the two lighten() or darken() functions to assign func .
  • Check if lastfunc func doesn't match to see if a change is needed.
    • If they are not equal, call func() and set lastfunc to func

This has the following advantages:

  • Everything is completed so as not to make lastfunc global.
  • The math is solid.
  • This calls the style change functions only if a change is required.

I also optimized the darken() and lighten() functions:

 function darken() { document.body.style.backgroundColor = "black"; $(".panel.content").css("color", "white"); } function lighten() { document.body.style.backgroundColor = "white"; $(".panel.content").css("color", "white"); } 

This small optimization saves jQuery finding your body , which should save a couple of milliseconds. Not a big difference, but it’s optimal.

Additional note: if you can get rid of the second style change in lighten and darken , we can get rid of the overhead of function calls in general and do it all in scroll()

 (function() { var lastColor; $(document).scroll(function() { var y = $(document).scrollTop(); var color = (Math.floor(((y + x) / (2 * x))) % 2) ? "red" : "blue"; if (color !== lastColor) { lastColor = color; document.body.style.color = color; } }); })(); 

Demonstration of the first solution:

 (function() { var lastfunc = darken; $(document).scroll(function() { var y = $(document).scrollTop(); var x = $("html").outerHeight(); var func = (Math.floor(((y + x) / (2 * x))) % 2) ? lighten : darken; if (func !== lastfunc) { lastfunc = func; func(); } }); })(); function darken() { document.body.style.backgroundColor = "black"; $(".panel.content").css("color", "white"); } function lighten() { document.body.style.backgroundColor = "white"; $(".panel.content").css("color", "white"); } 
 html, body, .panel { width: 100%; height: 100%; } body { background-color: black; overflow-y: visible; overflow-x: hidden; transition: background-color 500ms linear; } .panel { border: 2px solid red; } .content { color: white; text-align: center; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> <body> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> </body> 
+1
source

 $(document).scroll(function() { var viewportHeight = $("html").outerHeight(); var currentY = $(document).scrollTop(); var panelNumber = Math.floor(currentY / viewportHeight); if (panelNumber % 4 === 1 || panelNumber % 4 === 2) { lighten(); } else { darken(); } }); function darken() { $("body").css("background-color", "black"); $(".panel.content").css("color", "white"); } function lighten() { $("body").css("background-color", "white"); $(".panel.content").css("color", "black"); } 
 html, body, .panel { width: 100%; height: 100%; } body { background-color: black; overflow-y: visible; overflow-x: hidden; transition: background-color 500ms linear; } .panel { border: 2px solid red; } .content { color: white; text-align: center; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <body> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> </body> 

Not only the wrong order, the main problem is that it only starts when the user is in the exact Y for a change.

Yes this is correct. currentY % viewportHeight != 0 will not work. Scrolling is not smooth. Pulling the scroll bar can cause a change of 10,000 px / sec, but the browser displays 60 frames per second, which means that your currentY (scroll-y) will increase by 150 pixels every frame (you expect a 1px change). Therefore, if your code contains if(currentY === 100){} , it definitely will not work. currentY may have values ​​such as 0,50,80,99,120,...

It should be clear that currentY % viewportHeight != x not so different.

So if(0<currentY<500) would be a better option.

Now suppose viewportHeight = 500 . We can get panelNumber = Math.floor(currentY/viewportHeight) (=> 0,1,2,3,4,5 ...)

(Not clear from your question) Suppose you want a panel: 0 => black, 1 => white, 2 => white, 3 => black, 4 => black ... you can get a black panelNumber%4==0 || panelNumber%4==3 panelNumber%4==0 || panelNumber%4==3 .

[please change if you want something else]

+2
source

I know this a bit later, but I made a decision for this and did not manage to publish it.

So: "How is my decision different from another?"

I get the gap values ​​between all of your .blank and check where the viewport is located. This allows you to use borders, add any other divs between them, resize your divs, and this will not lose functionality.

 var elem = document.getElementsByClassName("blank"); var i; var marks = []; for (i = 0; i < elem.length; i++) { var rect = elem[i].getBoundingClientRect(); marks.push(rect.top); } $(document).scroll(function() { if (findi() % 2 == 1) { lighten(); } else { darken(); } }); function findi() { pos = 0; for (i = 0; i < marks.length; i++) { if (marks[i] < $(document).scrollTop()) { pos++; } } return (pos); } function darken() { $("body").css("background-color", "black"); $(".panel.content").css("color", "white"); } function lighten() { $("body").css("background-color", "white"); $(".panel.content").css("color", "black"); } 
 body { background-color: black; overflow-y: visible; overflow-x: hidden; transition: background-color 500ms linear; } html, body { padding: 0; margin: 0; } html, body, .panel { width: 100%; height: 100%; } .panel { border-bottom: 32px solid red; } .content { color: white; text-align: center; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> 
+2
source

You can use .hover() on $(document).ready(); I added an example if it works for you.

 $(document).ready(function() { $(".panel.content").hover(function(){ $("body").css("background-color", "white"); $(this).css("color", "black"); },function(){ $("body").css("background-color", "black"); $(this).css("color", "white"); }); }); $(document).scroll(function() { $(".panel.content").hover(function(){ $("body").css("background-color", "white"); $(this).css("color", "black"); },function(){ $("body").css("background-color", "black"); $(this).css("color", "white"); }); }); 
 html, body, .panel { width: 100%; height: 100%; } body { background-color: black; overflow-y: visible; overflow-x: hidden; transition: background-color 500ms linear; } .panel { border: 2px solid red; } .content { color: white; text-align: center; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> <body> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> </body> 
+1
source

Add a condition to your code

Math.floor(currentY / viewportHeight) % 4 == 1 || Math.floor(currentY / viewportHeight) % 4 == 2

and your code is working now.

Testing

If you run this code in java, it will display the same result as expected.

 public static void main(String...arr){ for(int i = 0; i<100; i++){ if(i%4 ==1 || i%4 == 2){ System.out.println("true"); } else { System.out.println("false"); } } } 

 $(document).scroll(function() { var viewportHeight = $("html").outerHeight(); var currentY = $(document).scrollTop(); if (Math.floor(currentY / viewportHeight) % 4 == 1 || Math.floor(currentY / viewportHeight) % 4 == 2) { lighten(); } else { darken(); } }); function darken() { $("body").css("background-color", "black"); $(".panel.content").css("color", "white"); } function lighten() { $("body").css("background-color", "white"); $(".panel.content").css("color", "black"); } 
  html, body, .panel { width: 100%; height: 100%; } body { background-color: black; overflow-y: visible; overflow-x: hidden; transition: background-color 500ms linear; } .panel { border: 2px solid red; } .content { color: white; text-align: center; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <body> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> </body> 
+1
source

I did this so that you can choose which panel sets the background color to white / black. You can do this by adding the black or white class to it, although the way you requested it makes sense after all. My solution also uses a class to change the background color of the body. This should facilitate a change in style.

 $(document).ready(init) function init(){ $(document).scroll(updateBackground) updateBackground() } function updateBackground(){ var w = $(window).width() var h = $(window).height() var panels = $('.panel') // get all panels on page for(var i=0;i<panels.length;i++){ // loop though each panel var panel = panels.eq(i) // get the current panel var panel_y = panel.offset().top - $(document).scrollTop() // get the panels y coordinate relative to the window var panel_height = panel.height() // get the panels height if(panel_y<=0 && panel_y+panel_height>0){ // check if the panel is in the visible area if(panel.hasClass('black')){ // check if the panel is set to make the background black $('body').removeClass('white') $('body').addClass('black') }else if(panel.hasClass('white')){ $('body').removeClass('black') $('body').addClass('white') } return // return, because we already found the visible panel } } } 
 html{ height: 100% } body{ margin: 0; padding: 0; transition: background-color 500ms linear; height: 100% } body.white{ background-color: white; color: black; } body.black{ background-color: black; color: white; } .panel{ width: 100%; height: 100%; box-sizing: border-box; padding: 50px; border: solid 1px #888888; text-align: center; overflow: hidden; } .panel > h1{ font-size: 38pt; } .panel > p{ font-size: 18pt; line-height: 200%; } 
 <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> </head <body> <div class="panel with-content black"> <h1>Content</h1> <p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p> </div> <div class="panel gap white"></div> <div class="panel with-content white"> <h1>Content</h1> <p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p> </div> <div class="panel gap black"></div> <div class="panel with-content black"> <h1>Content</h1> <p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p> </div> <div class="panel gap white"></div> <div class="panel with-content white"> <h1>Content</h1> <p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p> </div> <div class="panel gap black"></div> <div class="panel with-content black"> <h1>Content</h1> <p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p> </div> </body> </html> 
+1
source

What I want to do is to make sure that when the user scrolls down enough so that the panel with the content does not appear, the color should change from black to white. Then, when they scroll far enough so that the second panel with the content does not appear, it should change.

This statement is contrary to the order you specified. It follows from the statement that the color changes should be alternating, but the order mentioned in your question does not alternate.

Please see below code that changes colors on alternate div via scrolling.

 $(document).scroll(function() { var viewportHeight = $("html").outerHeight(); var currentY = $(document).scrollTop(); if (Math.floor(currentY / viewportHeight) % 2) { lighten(); } else { darken(); } }); function darken() { $("body").css("background-color", "black"); $(".panel.content").css("color", "white"); } function lighten() { $("body").css("background-color", "white"); $(".panel.content").css("color", "black"); } 
 html, body, .panel { width: 100%; height: 100%; } body { background-color: black; overflow-y: visible; overflow-x: hidden; transition: background-color 500ms linear; } .panel { border: 2px solid red; } .content { color: white; text-align: center; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script> <body> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> <div class="panel blank"> </div> <div class="panel content"> <h2> CONTENT </h2> </div> </body> 
0
source

Source: https://habr.com/ru/post/1270375/


All Articles