Rotsyx Rotsyx - 3 months ago 9
Javascript Question

Smooth Scroll to center current section after a given amount of time

I have a single page navigation site and all sections/navigation elements have

min-height
set to
100vh
. With that I have a smooth scroll snippet to navigate.

If I manual scroll and the section is not centered (like it would if I click on a menu item) I'd like it to be centered after a given amount of time. Note I don't want to disable scroll to just navigate via menu.

I was thinking about some js to be added with the smoothscroll code. Something to check section position offset and if it is not centered, smoothscroll it with some easing function.

https://jsfiddle.net/9ta3yh52/ take this as a reference, If a color is in more than 75% of view port, scroll to that element.

Thx for your help :)

EDIT / SOLUTION:

The closest approach has been given so far by @Hastig Zusammenstellen

http://stackoverflow.com/a/39188110/6717849

You have to modify it to your needs in order to match the number of sections you have. The logic is easy when sections are set to
height: 100vh
:

if (scrollTop <= sectionHeightHalf) {
$('html, body').animate({
scrollTop: $("#section1").offset().top
}, 300);
} else if (scrollTop >= sectionHeightHalf && scrollTop <= ($(window).height() * 2 - sectionHeightHalf)) {
$('html, body').animate({
scrollTop: $("#section2").offset().top
}, 300);
} else if (scrollTop >= sectionHeightHalf && scrollTop <= ($(window).height() * 3 - sectionHeightHalf)) {
$('html, body').animate({
scrollTop: $("#section3").offset().top
}, 300);
} else if (scrollTop >= sectionHeightHalf && scrollTop <= ($(window).height() * 4 - sectionHeightHalf)) {
$('html, body').animate({
scrollTop: $("#section4").offset().top
}, 300);
} else if (scrollTop >= sectionHeightHalf && scrollTop <= ($(window).height() * 5 - sectionHeightHalf)) {
$('html, body').animate({
scrollTop: $("#section5").offset().top
}, 300);

// etc etc

} else if (scrollTop >= ($(window).height() * 2 - sectionHeightHalf)) {
$('html, body').animate({
scrollTop: $("#lastsection").offset().top
}, 300);
}

Answer

New version was made using this code which was inspired or based on code from here.

It fixes the double scroll problem from last version but now seems to sometimes stick after it auto centers.

$(function() {
  $(window).scroll(function() {
    $('monitor').html('SCROLLING');
    clearTimeout($.data(this, 'scrollCheck'));
    $.data(this, 'scrollCheck', setTimeout(function() {
      $('monitor').html('PAUSED');
      var sectionHeightHalf = $(window).height() / 2;
      var scrollTop = $(window).scrollTop();
      if (scrollTop <= sectionHeightHalf) {
        $('html, body').animate({
          scrollTop: $("#about").offset().top
        }, 300);
      } else if 
        (scrollTop >= sectionHeightHalf && 
         scrollTop <= ($(window).height() * 2 - sectionHeightHalf)) {
          $('html, body').animate({
            scrollTop: $("#services").offset().top
          }, 300);
        } else if (scrollTop >= ($(window).height() * 2 - sectionHeightHalf)) {
          $('html, body').animate({
            scrollTop: $("#gallery").offset().top
          }, 300);
        }
    }, 300) );
  });
});
html, body {
  margin: 0;
  padding: 0;
}
section {
  position: relative;
}
markercenter, markerbottom, markerfixed, monitor {
  /* scaffolding, to be removed */
  display: flex; 
  justify-content: center; 
  align-items: center;
  height: 20px; width: 20px;
  font-size: 14px;
  color: white;
}
markercenter { 
  /* scaffolding, to be removed */
  /* these are here to judge center of screen for testing */
  position: absolute;
  top: 50%; transform: translateY(-50%);
  left: 50%; transform: translateX(-50%);
  background-color: black;
}
markerbottom { 
  /* scaffolding, to be removed */
  /* these are here to judge center of screen for testing */
  position: absolute;
  //top: 50%; transform: translateY(-50%);
  left: 50%; transform: translateX(-50%);
  bottom: -10px;
  height: 20px; width: 20px;
  font-size: 14px;
  color: white;
  background-color: black;
}
markerfixed {
  /* scaffolding, to be removed */
  /* these are here to judge center of screen for testing */
  position: fixed;
  top: 50%; transform: translateY(-50%);
  left: 50%; transform: translateX(-50%);
  height: 20px; width: 20px;
  background-color: rgba(251, 45, 45, 0.7);
}
monitor {
  /* scaffolding, to be removed */
  position: fixed;
  left: 50%; transform: translateX(-50%);
  bottom: 0;
  width: 100px;
  padding: 2px 10px 0px 10px;
  font-size: 14px;
  color: white; font-weight: bold;
  background-color: black;
}
section {
  width: 100%;
	min-height: 100vh;
}
#about{
  background-color: hsla(182, 100%, 85%, 0.5);
}
#services{
  background-color: hsla(61, 99%, 59%, 0.5);
}
#gallery{
  background-color: rgba(195, 251, 45, 0.5);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<section id="about">
  <markercenter>1</markercenter><markerbottom>1</markerbottom>
</section>
<section id="services">
  <markercenter>2</markercenter><markerbottom>2</markerbottom>
</section>
<section id="gallery">
  <markercenter>3</markercenter><markerbottom>3</markerbottom>
</section>
<monitor></monitor>
<markerfixed></markerfixed>

fiddle

https://jsfiddle.net/Hastig/9ta3yh52/13/

prior version with double scroll problem

https://jsfiddle.net/Hastig/9ta3yh52/12/

Comments