如何实现仅向下滚动时触发React Spring useInView动画?
解决React Spring useInView的滚动方向触发动画需求
要实现「向下滚动进入视口触发显示动画、向下移出不隐藏、向上移出才隐藏、再次向下进入重新触发」的效果,不能仅依赖useInView的once属性,需要结合滚动方向检测和自定义动画触发逻辑来实现,具体方案如下:
1. 实现滚动方向检测Hook
先写一个自定义Hook来实时获取当前的滚动方向:
import { useState, useEffect } from 'react'; const useScrollDirection = () => { const [scrollDirection, setScrollDirection] = useState('down'); useEffect(() => { let lastScrollY = window.scrollY; const handleScroll = () => { const currentScrollY = window.scrollY; const direction = currentScrollY > lastScrollY ? 'down' : 'up'; if (direction !== scrollDirection) { setScrollDirection(direction); } lastScrollY = currentScrollY; }; window.addEventListener('scroll', handleScroll, { passive: true }); return () => window.removeEventListener('scroll', handleScroll); }, [scrollDirection]); return scrollDirection; };
2. 结合useInView和useSpring实现目标动画
通过滚动方向和元素视口可见性的组合,精准控制动画的触发时机:
import { useInView, useSpring, animated } from '@react-spring/web'; const RevealElement = () => { const scrollDirection = useScrollDirection(); const [ref, isInView] = useInView({ threshold: 0.7 }); const [style, api] = useSpring(() => ({ opacity: 0, x: 100, config: { duration: 500 } })); useEffect(() => { // 向下滚动且元素进入视口:触发显示动画 if (isInView && scrollDirection === 'down') { api.start({ opacity: 1, x: 0 }); } // 向上滚动且元素移出视口:触发隐藏动画 else if (!isInView && scrollDirection === 'up') { api.start({ opacity: 0, x: 100 }); } // 向下滚动移出视口:保持当前显示状态,不执行隐藏逻辑 }, [isInView, scrollDirection, api]); return ( <animated.div ref={ref} style={style}> {/* 这里放置你的元素内容 */} </animated.div> ); };
逻辑说明
- 滚动方向检测:通过对比前后滚动位置,判断当前是向上还是向下滚动。
- 视口检测:
useInView的threshold: 0.7保持你原有的触发条件(元素70%进入视口时判定为可见)。 - 动画触发规则:
- 仅当向下滚动+元素进入视口时,执行从右侧滑入并显示的动画。
- 仅当向上滚动+元素移出视口时,执行滑出并隐藏的动画。
- 向下滚动导致元素移出视口时,元素保持显示状态,不会消失。
内容的提问来源于stack exchange,提问作者Zaw Htet Aung
相关产品推荐
相关产品推荐

