我已经阅读了整个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和钩子进行尝试。
useRef
被附加到滚动目标位置,以便从网站上限找到其偏移的顶部。
我使用useState
在点击状态之间切换以触发滚动。
我使用useSpring
触发一个动画,该动画从0到滚动目标的滚动顶部,也就是getBoundingClientRect().top
。
有人可以协助解决这个问题吗?
在线上没有太多解释,谢谢!
答案 0 :(得分:1)
useSpring
返回用于设置/更新动画值的函数。您可以使用该函数为动画变量分配新值。然后,您可以使用onFrame
属性来更新滚动位置。
这样定义您的spring
:
const [y, setY] = useSpring(() => ({
immediate: false,
y: 0,
onFrame: props => {
window.scroll(0, props.y);
},
config: config.slow,
}));
然后使用setY
函数启动弹簧,如下所示:
<button
onClick={() => {
setY({ y: scrollDestinationRef.current.getBoundingClientRect().top });
}}
>
Click to scroll
</button>
单击按钮时,它将在您的spring中为y
变量分配一个新值,并且每次更新时都会调用onFrame
函数。
请注意,我们从window.scroll
的{{1}}属性调用onFrame
函数。
查看工作演示here。
答案 1 :(得分:1)
最后通过 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
答案 2 :(得分:0)
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)
确实会返回stop
之外的set
方法。但是我无法使其兼容。我将其发布到相关的github issue。如果您读过这篇文章,也许已经有了一个很好的答案:)
目前,它使用带有isStopped
标志的小解决方法。
更新:
似乎stop
fn实际上有些可疑,应该在v9 canary中解决。由于v9尚未稳定,因此尚未测试。