scroll to section by section

后端 未结 2 1383
[愿得一人]
[愿得一人] 2021-02-02 14:55

I have HTML markup:

HTML:


    
2条回答
  •  既然无缘
    2021-02-02 15:28

    Interesting

    I stole this code, changed the layout and tried to add the functions you mentioned (1. scroll-snap + 2. scroll when link is clicked). Unfortunately, I can't have this second function to work.

    1. Adding scroll-snap is not a problem

    You need scroll-snap-type: y mandatory; on the container and scroll-snap-align: start; on the sections.

    var doc = window.document,
      context = doc.querySelector('.js-loop'),
      clones = context.querySelectorAll('.is-clone'),
      disableScroll = false,
      scrollHeight = 0,
      scrollPos = 0,
      clonesHeight = 0,
      i = 0;
    
    function getScrollPos () {
      return (context.pageYOffset || context.scrollTop) - (context.clientTop || 0);
    }
    
    function setScrollPos (pos) {
      context.scrollTop = pos;
    }
    
    function getClonesHeight () {
      clonesHeight = 0;
    
      for (i = 0; i < clones.length; i += 1) {
        clonesHeight = clonesHeight + clones[i].offsetHeight;
      }
    
      return clonesHeight;
    }
    
    function reCalc () {
      scrollPos = getScrollPos();
      scrollHeight = context.scrollHeight;
      clonesHeight = getClonesHeight();
    
      if (scrollPos <= 0) {
        setScrollPos(1); // Scroll 1 pixel to allow upwards scrolling
      }
    }
    
    function scrollUpdate () {
      if (!disableScroll) {
        scrollPos = getScrollPos();
    
        if (clonesHeight + scrollPos >= scrollHeight) {
          // Scroll to the top when you’ve reached the bottom
          setScrollPos(1); // Scroll down 1 pixel to allow upwards scrolling
          disableScroll = true;
        } else if (scrollPos <= 0) {
          // Scroll to the bottom when you reach the top
          setScrollPos(scrollHeight - clonesHeight);
          disableScroll = true;
        }
      }
    
      if (disableScroll) {
        // Disable scroll-jumping for a short time to avoid flickering
        window.setTimeout(function () {
          disableScroll = false;
        }, 40);
      }
    }
    
    function init () {
      reCalc();
      
      context.addEventListener('scroll', function () {
        window.requestAnimationFrame(scrollUpdate);
      }, false);
    
      window.addEventListener('resize', function () {
        window.requestAnimationFrame(reCalc);
      }, false);
    }
    
    if (document.readyState !== 'loading') {
      init()
    } else {
      doc.addEventListener('DOMContentLoaded', init, false)
    }
    html,
    body {
      height: 100%;
      overflow: hidden;
    }
    
    .Loop {
      position: relative;
      height: 100%;
      overflow: scroll;
      -webkit-overflow-scrolling: touch;
      scroll-snap-type: y mandatory;
    }
    
    section {
      position: relative;
      text-align: center;
      height: 100%;
      scroll-snap-align: start;
    }
    
    ::scrollbar {
      display: none;
    }
    
    
    body {
      font-family: "Avenir Next", Helvetica, sans-serif;
      font-weight: normal;
      font-size: 100%;
      position: relative;
    }
    
    nav {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      z-index: 10;
    }
    
    nav ul {
      display: flex;
      justify-content: space-around;
      margin: 0;
      padding: 1rem 0;
    }
    
    nav ul li{
      display: flex;
      justify-content: space-around;
    }
    
    .nav-link{
      text-decoration: none;
      color: grey
    }
    
    .one {
      background: black;
    }
    .two {
      background: darkblue;
    }
    .three {
      background: lightgreen;
    }
    .four {
      background: lightcoral;
    }
    .five {
      background: lightskyblue;
    }
    .six {
      background: orange;
    }
    
    h1 {
      margin: 0;
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      width: 100%;
      font-size: 80px;
      letter-spacing: 5px;
      color: #fff;
      text-transform: uppercase;
    }
    
    

    One

    Two

    Three

    Four

    Five

    Six

    One

    Two

    1. Adding the scrolling when you click on the link is a problem

    With a normal container you only need to add the scroll-behaviour: smooth; to it. But here if you do that, you will lose the loop illusion because you will see it scroll back to the first instead of seemingly continue. (and it will also start an infinite back and forth scrolling that I couldn't fix yet)

    var doc = window.document,
      context = doc.querySelector('.js-loop'),
      clones = context.querySelectorAll('.is-clone'),
      disableScroll = false,
      scrollHeight = 0,
      scrollPos = 0,
      clonesHeight = 0,
      i = 0;
    
    function getScrollPos () {
      return (context.pageYOffset || context.scrollTop) - (context.clientTop || 0);
    }
    
    function setScrollPos (pos) {
      context.scrollTop = pos;
    }
    
    function getClonesHeight () {
      clonesHeight = 0;
    
      for (i = 0; i < clones.length; i += 1) {
        clonesHeight = clonesHeight + clones[i].offsetHeight;
      }
    
      return clonesHeight;
    }
    
    function reCalc () {
      scrollPos = getScrollPos();
      scrollHeight = context.scrollHeight;
      clonesHeight = getClonesHeight();
    
      if (scrollPos <= 0) {
        setScrollPos(1); // Scroll 1 pixel to allow upwards scrolling
      }
    }
    
    function scrollUpdate () {
      if (!disableScroll) {
        scrollPos = getScrollPos();
    
        if (clonesHeight + scrollPos >= scrollHeight) {
          // Scroll to the top when you’ve reached the bottom
          setScrollPos(1); // Scroll down 1 pixel to allow upwards scrolling
          disableScroll = true;
        } else if (scrollPos <= 0) {
          // Scroll to the bottom when you reach the top
          setScrollPos(scrollHeight - clonesHeight);
          disableScroll = true;
        }
      }
    
      if (disableScroll) {
        // Disable scroll-jumping for a short time to avoid flickering
        window.setTimeout(function () {
          disableScroll = false;
        }, 40);
      }
    }
    
    function init () {
      reCalc();
      
      context.addEventListener('scroll', function () {
        window.requestAnimationFrame(scrollUpdate);
      }, false);
    
      window.addEventListener('resize', function () {
        window.requestAnimationFrame(reCalc);
      }, false);
    }
    
    if (document.readyState !== 'loading') {
      init()
    } else {
      doc.addEventListener('DOMContentLoaded', init, false)
    }
    html,
    body {
      height: 100%;
      overflow: hidden;
    }
    
    .Loop {
      position: relative;
      height: 100%;
      overflow: scroll;
      -webkit-overflow-scrolling: touch;
      scroll-snap-type: y mandatory;
      scroll-behavior: smooth;
    }
    
    section {
      position: relative;
      text-align: center;
      height: 100%;
      scroll-snap-align: start;
    }
    
    ::scrollbar {
      display: none;
    }
    
    
    body {
      font-family: "Avenir Next", Helvetica, sans-serif;
      font-weight: normal;
      font-size: 100%;
      position: relative;
    }
    
    nav {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      z-index: 10;
    }
    
    nav ul {
      display: flex;
      justify-content: space-around;
      margin: 0;
      padding: 1rem 0;
    }
    
    nav ul li{
      display: flex;
      justify-content: space-around;
    }
    
    .nav-link{
      text-decoration: none;
      color: grey
    }
    
    .one {
      background: black;
    }
    .two {
      background: darkblue;
    }
    .three {
      background: lightgreen;
    }
    .four {
      background: lightcoral;
    }
    .five {
      background: lightskyblue;
    }
    .six {
      background: orange;
    }
    
    h1 {
      margin: 0;
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      width: 100%;
      font-size: 80px;
      letter-spacing: 5px;
      color: #fff;
      text-transform: uppercase;
    }
    
    

    One

    Two

    Three

    Four

    Five

    Six

    One

    Two

    I know this code is not 100% functional yet, but I think it can lead us to a better answer.

提交回复
热议问题