滚动位置> 0后如何平滑向下滚动到元素?

时间:2019-05-10 14:32:34

标签: javascript

我的页面顶部有一个全屏预告片。当用户开始滚动时,我希望整个页面自动平滑地向下滚动到以下部分。

不幸的是,以下代码不起作用。如前所述,它根本不会滚动,并且当我不将scrolling变量设置为true以避免多次执行scrollIntoView时,它非常慢。

使用香草JS修复此问题的好方法是什么?

示例,在Chrome中进行了测试:

let scrolling = false;

window.onscroll = () => {
  const offset = window.pageYOffset;
  if (offset > 0 && offset < window.innerWidth && !scrolling) {
    scrolling = true;
    document.querySelector('.somecontent').scrollIntoView({behavior:'smooth'});
  }
  
  if (offset >= window.innerWidth) {
    scrolling = false;
  }
}
.someteaser {
  background: blue;
  height: 100vh;
  width: 100vw;
}

.somecontent {
  background: red;
  height: 200vh;
  width: 100vw;
}
<div class="someteaser"></div>
<div class="somecontent"></div>

//更新

所以问题出在行为:“平滑”选项。没有它,滚动将起作用,但当然不再平滑了。这似乎是scorllIntoView上的错误,我不太了解。我的临时解决方案使用此脚本,该脚本可以正常运行:https://github.com/cferdinandi/smooth-scroll

1 个答案:

答案 0 :(得分:1)

这个问题使我感兴趣,所以我这样做了,试图扩大它的范围(它是上下自滚动的)。我希望它适合您的问题..

(最好在完整页面上使用摘录)

const
  AllSections   = document.querySelectorAll('body > section'), // all target Section reference
  SectionsCount = AllSections.length,
  opt           = {behavior: "smooth", block: "start"};

var
  NoSmooth       = true, // autoScroll is off
  Last_W_PosY    = 0,    // used to determine scrolling event direction
  Smooth_Id      = 0,    // setTimeout for launching autoScroll
  Smooth_End     = 0,    // setinterval to detect end of autoScroll
  Scroll2Section = -1;   // target section for autoScroll

window.onscroll = () => {
  clearTimeout(Smooth_Id);
  let
    W_PosY    = window.pageYOffset,
    W_height  = window.innerHeight,
    direction = (Last_W_PosY < W_PosY) ? 'down' : 'up';

  if (NoSmooth){
    Scroll2Section = -1;
    let parts_Section = true;

    for(let i = 0; i< SectionsCount; i++){
      let SectionRect = AllSections[i].getBoundingClientRect();
      if ( SectionRect.y <= 0 && (SectionRect.height + SectionRect.y) >= W_height )
      {
        parts_Section = false;
        break;
      }
    }
    if (parts_Section){
      if (direction==='down') {
        for (let i = 0; i< SectionsCount; i++){
          if (AllSections[i].getBoundingClientRect().y > 0 ) {
            Scroll2Section = i;
            break;
          }
        }
      }
      if (direction==='up') {
        for (let i = SectionsCount; i-->0;){
          if (AllSections[i].getBoundingClientRect().y < 1) { // somme top position are not precise
            Scroll2Section = i;
            break;
          }
        }
      }
    }

    if (parts_Section) {
      Smooth_Id = setTimeout(Smooth_Action, 300) // reaction delay for auto scroll
    }
  }
  Last_W_PosY = W_PosY;
}

function Smooth_Action(){
  NoSmooth = false;
  AllSections[Scroll2Section].scrollIntoView( opt );
  clearInterval(Smooth_End);
  Smooth_End = setInterval(Wait_Smooth_Finish, 100 )
}

function Wait_Smooth_Finish(){
  let W_PosY = window.pageYOffset;
  if (Last_W_PosY==W_PosY) {
    NoSmooth = true;
    clearInterval(Smooth_End);
  }
  Last_W_PosY = W_PosY;
}
body           { margin: 0; }
body > section { display: block; width: 100%; margin: 0  }
.content_0     { height: 100vh; background: #001f3f; }
.content_1     { height: 120vh; background: #FF851B; }
.content_2     { height: 140vh; background: #39CCCC; }
.content_3     { height: 160vh; background: #F012BE; }
p { display:inline-block; margin:20px; padding:3px; background-color:#f0f8ff }
<section class="content_0"> <p>1 / 4</p> </section>
<section class="content_1"> <p>2 / 4</p> </section>
<section class="content_2"> <p>3 / 4</p> </section>
<section class="content_3"> <p>4 / 4</p> </section>