如何使用 react-spring 滚动到元素?
Posted
技术标签:
【中文标题】如何使用 react-spring 滚动到元素?【英文标题】:How to scroll to an element using react-spring? 【发布时间】:2019-12-31 11:47:22 【问题描述】:我已经阅读了整个 react-spring
文档,但似乎没有明确的方法来做到这一点。
我的尝试:
import React, useRef, useState from "react"
import animated, useSpring from "react-spring"
const App = () =>
const scrollDestinationRef = useRef()
const [elementScroll, setElementScroll] = useState(false)
const buttonClickHandler = () => setElementScroll(prevState => !prevState)
const scrollAnimation = useSpring(
scroll: elementScroll
? scrollDestinationRef.current.getBoundingClientRect().top
: 0
)
return (
<main>
/* Click to scroll to destination */
<animated.button
onClick=buttonClickHandler
scrollTop=scrollAnimation.scroll
style=
height: "1000px",
width: "100%",
backgroundColor: "tomato"
>
Scroll to destination
</animated.button>
/* Scroll destination */
<div
ref=scrollDestinationRef
style=
height: "200px",
width: "200px",
backgroundColor: "green"
></div>
</main>
)
export default App
我正在尝试使用 ref 和 hooks。
useRef
附加到滚动目的地,以便找到它与网站天花板的偏移顶部。
我使用useState
在点击状态之间切换以触发滚动。
我使用useSpring
触发从0 到滚动目标的滚动顶部的动画,也就是getBoundingClientRect().top
。
谁能帮忙解决这个问题?
网上解释不多,谢谢!
【问题讨论】:
【参考方案1】:useSpring
返回一个设置/更新动画值的函数。您可以使用该函数为动画变量分配新值。然后,您可以使用onFrame
属性来更新滚动位置。
像这样定义你的spring
:
const [y, setY] = useSpring(() => (
immediate: false,
y: 0,
onFrame: props =>
window.scroll(0, props.y);
,
config: config.slow,
));
然后使用setY
函数启动spring,像这样:
<button
onClick=() =>
setY( y: scrollDestinationRef.current.getBoundingClientRect().top );
>
Click to scroll
</button>
当您单击按钮时,它将在您的 spring 中为 y
变量分配一个新值,并且每次更新都会调用 onFrame
函数。
请注意,我们从useSpring
中的onFrame
属性调用window.scroll
函数。
查看工作演示 here。
【讨论】:
非常感谢。当您在加载后按一次按钮后向上和向下滚动时,它不再起作用。它只在第一次工作。请问可以修改一下吗?【参考方案2】:const targetElement = useRef(null)
const [, setY] = useSpring(() => ( y: 0 ))
let isStopped = false
const onWheel = () =>
isStopped = true
window.removeEventListener('wheel', onWheel)
const scrollToTarget = () =>
const element = targetElement.current
const value = window.scrollY + element.getBoundingClientRect().top
window.addEventListener('wheel', onWheel)
setY(
y: value,
reset: true,
from: y: window.scrollY ,
onRest: () =>
isStopped = false
window.removeEventListener('wheel', onWheel)
,
onFrame: props =>
if (!isStopped)
window.scroll(0, props.y)
)
此版本还允许用户通过使用wheel
事件来摆脱强制滚动。 (我个人讨厌强制滚动:D)
useSpring(fn)
除了set
之外,还返回一个stop
方法。但我无法让它与它一起工作。我将其发布到相关的github issue。如果你读到这个,也许已经有一个很好的答案了:)
目前它使用isStopped
标志的小解决方法。
更新:
似乎stop
fn 确实有问题,应该在v9 canary 中解决。尚未测试,因为 v9 还不稳定。
【讨论】:
【参考方案3】:终于在通过https://github.com/pmndrs/react-spring/issues/544 之后,Yannick Schuchmann 的回答对我有用,我只需将 onFrame 更改为 onChange
我为解决方案制作了一个自定义挂钩:https://github.com/TomasSestak/react-spring-scroll-to-hook
react-sring 版本:9.0.0-rc.3
【讨论】:
在同一链接上为 react-spring 9+ 更新以上是关于如何使用 react-spring 滚动到元素?的主要内容,如果未能解决你的问题,请参考以下文章
React JS:如何在 react-spring 中使用响应式样式
将 react-spring 用于 react-native