当内容在滚动时改变高度时如何检测滚动方向

Posted

技术标签:

【中文标题】当内容在滚动时改变高度时如何检测滚动方向【英文标题】:How to detect scroll direction when content changes height on scroll 【发布时间】:2021-03-23 15:44:05 【问题描述】:

在以静态尺寸滚动页面时检测滚动方向非常简单。但是,如果其中一个元素是粘性标题并在滚动时更改高度,它会保持更改pageYOffset 并进入无限循环上下跳跃。

Example sandbox 如果你滚动到它开始收缩的地方,它就会开始跳跃。

我想出的一些可能的解决方案是添加一个垫片,以在粘性导航变小时进行补偿。但这需要在实际组件中进行。想知道是否有办法只在 useScrollDirection 钩子中使用 js。

我尝试过的另一件事是使用 document.documentElement.scrollHeight 并检查大小变化,但这也没有帮助。

【问题讨论】:

【参考方案1】:

只是一个建议。我认为你没有充分利用position: sticky。您不需要事件侦听器来实现您想要的行为。您可以完全使用 CSS 来完成此操作,并让浏览器为您处理一切。

.app 
  font-family: sans-serif;
  text-align: center;
  height: 300vh;


.nav 
  position: sticky;
  top: -120px;
  height: 150px;
  background: aquamarine


.nav_item 
   position: sticky;
    top: 0px;
    margin: 0;
<div class="app">
  <h1>Hello CodeSandbox</h1>
  <nav class="nav">
    <p class="nav_item">Hello</p>
  </nav>
  <h2>Start editing to see some magic happen!</h2>
</div>

【讨论】:

感谢@slumbergeist!我可能会尝试利用这个!但这个例子相当简化为真实应用程序的本质。在真正的应用程序中,字体高度和其他一些事情发生了变化,这需要滚动发出信号。 你的解决方案绝对很棒,只是我不想用粘性子导航重写每个实现? 我已经通过字体更改更新了示例。【参考方案2】:

我遇到了同样的问题,一位同事建议我收听wheel 事件。所以我实现了以下反应钩子:

const useLastMouseWheelDirection = () => 
  const [lastMouseWheelDirection, setLastMouseWheelDirection] = useState(
    undefined
  )

  useEffect(() => 
    const handler = (event) => 
      setLastMouseWheelDirection(event.deltaY >= 0 ? 'down' : 'up')
    
    window.addEventListener('wheel', handler)
    return () => window.removeEventListener('wheel', handler)
  , [])

  return lastMouseWheelDirection

这个解决方案有一些严重的局限性:

显然触摸事件被忽略 单击并拖动滚动条不会触发事件

对于所需行为的另一个副作用是它不会考虑元素是否甚至溢出,尽管可以扩展钩子以捕获这种情况。

更多MDN Web Docs状态:

注意:不要将滚轮事件与滚动事件混淆。 Wheel 事件的默认操作是特定于实现的,并且不一定调度滚动事件。即使是这样,wheel 事件中的 delta* 值也不一定反映内容的滚动方向。因此,不要依赖 wheel 事件的 delta* 属性来获取滚动方向。而是在滚动事件中检测目标的scrollLeft和scrollTop的值变化。

所以请对这个答案持保留态度。

【讨论】:

以上是关于当内容在滚动时改变高度时如何检测滚动方向的主要内容,如果未能解决你的问题,请参考以下文章

vant中tab标签切换时会改变内容滚动高度

iscroll5 滚动条根据内容高度自动显示隐藏及强制横屏时方向错位

当内容长于高度时,可以让 jqueryUI 对话框滚动条从顶部开始吗?

如何使DIV的高度固定,当超出固定高度时,让文字自动上下循环滚动

每当离开滚动时,滚动视图就会在上下方向返回相同的位置

如何使DIV的高度固定,当超出固定高度时,出现自动滚动条