1

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

https://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);
  }
Community
  • 1
  • 1
Rotsyx
  • 15
  • 3
  • I combined [this](http://stackoverflow.com/a/17573963/3377049) with [this](http://stackoverflow.com/a/22330718/3377049) to [get you started](http://jsfiddle.net/Hastig/hxp6bq52/) on the start/stop part of it – Hastig Zusammenstellen Aug 27 '16 at 10:38
  • That's a good start! Thanks for the answer but now I need to get the current visible section to scroll at it. Any hint? – Rotsyx Aug 27 '16 at 11:32
  • this project might have some of the answer we are looking for. http://projects.lukehaas.me/scrollify/ https://github.com/lukehaas/Scrollify – Rotsyx Aug 27 '16 at 18:52
  • Sorry, missed your comment. I'll check that out later for some ideas on the double scroll problem my current versions has. – Hastig Zusammenstellen Aug 28 '16 at 05:01
  • I would suggest the king of full page libraries :) http://alvarotrigo.com/fullPage/examples/normalScroll.html – Alvaro Sep 05 '16 at 10:24

2 Answers2

1

You could use the DOMMouseScroll and mousewheel events with animate() and scrollTop() the go to the good window position straight away.

Here is a fiddle adaptation of your code.

Piece of jQuery code :

$('#about').on('DOMMouseScroll mousewheel', function (e) {
    // scroll down
    if(e.originalEvent.detail > 0 || e.originalEvent.wheelDelta < 0) {
    $('html, body').animate({
      scrollTop: $('#services').offset().top
    });
  }
});

Sources :

Hope it helps.

JazZ
  • 4,469
  • 2
  • 20
  • 40
  • That's not the desired behaviour, I want the site to scroll normally, not section by section. But as soon as scroll stops, center the current section. Thanks for your answer anyway, it gave me some ideas. – Rotsyx Aug 27 '16 at 11:34
0

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/

Community
  • 1
  • 1
Hastig Zusammenstellen
  • 4,286
  • 3
  • 32
  • 45
  • Indeed, this is what I was thinking about but even If i'm scrolling at some point it scrolltops to some section. Function should be executed only after a cooldown, and then reset the cooldown if I scroll again. – Rotsyx Aug 29 '16 at 15:37
  • @Rotsyx improved but imperfect version added – Hastig Zusammenstellen Aug 29 '16 at 22:32
  • This last version looks way better now, It sometimes sticks to center but I don't see how it could be improved in this lines of code! Thank you very much for your time I learnt many things trying to figure this out ;) – Rotsyx Aug 31 '16 at 17:20