仅允许滚动以在某些元素上停止

时间:2018-08-03 22:45:37

标签: javascript jquery scroll

我尝试搜索是否已经存在有关此问题的信息,但找不到任何内容-很抱歉,如果这实际上是重复项!

我在某些网站上看到了一项功能,该功能在滚动时会强制将滚动停止点停止在特定元素上,而不是在用户实际停止滚动的位置停止。

我想这可以通过jQuery来实现,但是似乎找不到任何文档或有关它的帮助文章。

所以,这是HTML的示例...

<div id="one" class="block"></div>
<div id="two" class="block"></div>
<div id="three" class="block"></div>

以此为CSS ...

#one {
background: red;
}

#two {
background: green;
}

#three {
background: yellow;
}

.block {
width: 200px;
height: 100vh;
}

我想要实现的是,当用户将其浏览器从div“ one”滚动到div“ two”时,一旦他们开始滚动div“ two”,然后停止滚动,浏览器就会自动跳转他们,以便他们完整地看到div'two',而不是div'one'的最底层,然后是div'two'的大部分-我确实看过它,但是不知道怎么做!

我希望这很有意义,在此先感谢任何人都可以提供的帮助或见解...

1 个答案:

答案 0 :(得分:0)

我不太记得,但是我想有很多方法可以实现您想要的。我想到的一件事是将div包裹起来,并制作一个具有完整高度的单独的隐藏div。我在下面做了这个特别的解决方案:

一旦滚动接近阈值,我将移至应查看的div,反之亦然。这是一个可行的解决方案FIDDLE

HTML

<div id="phantom"></div>
<div id="wrapper">
<div id="one" class="block"></div>
<div id="two" class="block"></div>
<div id="three" class="block"></div>
</div>

CSS

#one {
background: red;
}

#two {
background: green;
}

#three {
background: yellow;
}

.block {
width: 200px;
height: 100vh;
}

#wrapper {
  overflow:hidden;
  position:fixed;
  top:0px;
}

#phantom {
  visibility:hidden;
}

JS

!function(){
    //the array of divs
    var divs = Array.prototype.slice.call(document.getElementsByClassName("block")),            count = divs.length,
        wrapper = document.getElementById("wrapper"),
      phantom = document.getElementById("phantom"),
      //the speed of scroll
      scrollStep = 5,
      //total length of phantom div
            totalLength = Array.prototype.slice.call(wrapper.children).reduce(function(ac,d,i,a){return ac += d.clientHeight},0),
      //store the animation frame here
            currentFrame;
      //wrapper is overflow hidden
    wrapper.style.height = totalLength/count + "px";
  //phantom has full height
  phantom.style.height = totalLength + "px";
  //add listener for scroll
    window.addEventListener("scroll",function(){
        //throttle the function
      if(this._busy){return};
        this._busy = true;
            var that = this;
            window.requestAnimationFrame(function(){
            that._busy = false;
                    var heightOfDocument = Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),
            totalScroll = Math.max(document.body.scrollTop,document.documentElement.scrollTop),
          //which element should we look at?
                    whichElement = Math.round(totalScroll/heightOfDocument*count);
          //if we are already around, don't do anything
          if(divs[whichElement]._current){
            return;
          } else {
            //cancel the last animation if any and start a new one
            window.cancelAnimationFrame(currentFrame);
            divs.forEach(function(d,i){delete d._current});
            moveTo(divs[whichElement]);
          }
      });
    },false);
  //helper function to linearly move to elements
    function moveTo(node){
            node._current = true;
            var top = node.offsetTop,
                    current = node.parentNode.scrollTop,
                    distance = top - current,
                    step = distance < 0 ? -scrollStep : scrollStep;
            if(Math.abs(distance) < scrollStep){
        node.parentNode.scrollTop = top;
                return;
      } else {
        node.parentNode.scrollTop += step;
      }
      //store the current frame
            currentFrame = window.requestAnimationFrame(function(){
                moveTo(node);
            });
    }
}();

您显然需要附加“调整大小”事件以更新totalLength的值,并在包装​​器和幻像上设置正确的新长度。您还可以实现缓动功能,以根据自己的喜好修改滚动行为。我把它们留给你做功课。