如何中途跳过framer-motion动画延迟,滚动时立即触发淡出?
滚动触发立即淡出动画的实现方案
需求说明
页面加载时显示全屏蓝色遮罩div,默认20秒延迟后执行2秒的淡出动画,动画结束后隐藏该div;要求用户滚动页面时立即跳过延迟,触发淡出动画。
实现思路
利用React状态控制Framer Motion的动画延迟,结合滚动事件监听触发状态变更,同时通过ref避免重复触发动画:
- 用状态变量控制动画的延迟时间,默认20秒,滚动时改为0秒
- 用ref标记动画是否已触发,防止滚动事件多次触发状态更新
- 监听滚动事件后立即移除监听,避免重复执行
- 用React ref直接获取遮罩元素,替代
document.querySelector更符合React规范
完整代码
import "./styles.css"; import { motion } from "framer-motion"; import { useEffect, useState, useRef } from "react"; export default function App() { const [skipDelay, setSkipDelay] = useState(false); const hasTriggered = useRef(false); const maskRef = useRef<HTMLDivElement>(null); useEffect(() => { const handleScroll = () => { if (!hasTriggered.current) { hasTriggered.current = true; setSkipDelay(true); document.removeEventListener("scroll", handleScroll); } }; document.addEventListener("scroll", handleScroll); return () => document.removeEventListener("scroll", handleScroll); }, []); return ( <> <motion.div ref={maskRef} style={{ background: "blue", position: "fixed", top: 0, left: 0, width: "100%", height: "100%" }} onAnimationComplete={() => { if (maskRef.current) { maskRef.current.style.display = "none"; } }} initial={{ opacity: 1 }} animate={{ opacity: 0 }} transition={{ delay: skipDelay ? 0 : 20, duration: 2 }} /> <p> distinctio vitae voluptatibus ipsa veritatis sequi laborum quasi explicabo! Vero, accusamus libero, assumenda animi porro dolorum reprehenderit totam laboriosam harum mollitia nihil. Dolores, laudantium? Nisi amet voluptatum officia enim error atque consequuntur nobis similique quibusdam numquam illum nesciunt laborum a maxime quidem qui vitae rerum cum, incidunt voluptatem modi? Quam sit vitae autem temporibus voluptates voluptatum. Perspiciatis expedita voluptatibus laborum, iusto alias recusandae odit omnis. Earum, maxime fugit. Deleniti cupiditate obcaecati vero libero atque error modi tempore maxime consequuntur quod exercitationem, possimus ad omnis quas autem culpa ut ratione asperiores? Explicabo blanditiis debitis dolor. Quia architecto quam enim dolores laudantium impedit odio provident voluptatum quaerat. Repellendus labore, voluptates placeat nobis dicta optio quia in dolores porro, deserunt officiis, magnam culpa totam ea est autem veritatis minus quaerat. Quisquam, omnis consectetur porro, vitae deleniti enim pariatur, sed voluptatem fugiat libero illo. Veritatis autem laudantium, a neque officia consectetur optio alias repudiandae ea quia pariatur saepe tenetur ab dolorum reiciendis rerum qui iste quisquam delectus accusantium corrupti obcaecati maxime non sunt. Non dolores illum beatae minus quisquam, a tempore facere voluptatum aspernatur optio veritatis delectus fuga! Alias aliquid, nostrum atque explicabo, eum, modi culpa iusto minus ad omnis sint quod corrupti? Dolorem officia, id aliquam, accusantium tempore dolorum nisi deleniti ea dignissimos consequuntur voluptatem quas nihil quod facere, excepturi quam hic. Repellat quas provident aliquam perspiciatis temporibus voluptates quaerat? Repellendus blanditiis nobis delectus fugit vero voluptas placeat quidem accusantium quam. Ipsa corrupti laborum magni reprehenderit dolore nisi autem sint quisquam quia quidem. Vero quod consequatur perspiciatis esse mollitia consequuntur nobis, sit dolores, placeat nostrum unde deserunt obcaecati officiis modi ab provident quaerat assumenda eaque aliquid voluptates ducimus dignissimos, incidunt dolorum nam. Deleniti cumque est eaque maiores molestias voluptatibus totam libero praesentium a magnam, perferendis iste distinctio blanditiis veniam nobis nisi molestiae, sapiente inventore soluta magni ex! Assumenda autem error voluptatem tempora! Suscipit, quia repellat tenetur autem molestiae cum, mollitia fuga labore facere aut, amet nam quisquam quod magni itaque aliquid eaque vitae saepe quae soluta veniam. Eum voluptatem enim cum, qui maiores, sed quibusdam atque dolorem soluta recusandae obcaecati nostrum laboriosam impedit. Quia porro voluptates ex amet obcaecati a hic rerum, similique quisquam voluptate nemo at. Incidunt tempore ad laborum nihil sapiente! Maiores sit consequuntur eos dolor! Nulla porro vel hic et mollitia quis vero, temporibus est cum, ratione modi molestiae laboriosam eum dignissimos suscipit. Inventore facere voluptate earum obcaecati quos atque hic similique voluptates veritatis, at debitis ullam maxime praesentium nesciunt quasi magni blanditiis maiores veniam tempore nemo iusto? Tempore, at voluptatem. Voluptatem facilis ratione fuga non iusto, consequatur autem temporibus facere reiciendis provident deserunt accusantium doloribus culpa neque. Corrupti, expedita! Autem obcaecati incidunt necessitatibus iste deserunt in adipisci molestiae suscipit, voluptas soluta vitae? Earum, consequatur nam odio quo pariatur obcaecati vel adipisci deserunt facere culpa fugiat ipsum nisi saepe repudiandae possimus, quisquam illo in suscipit. Distinctio harum repudiandae dolorem animi repellendus quo vitae accusantium saepe illum omnis, reprehenderit perspiciatis quod iusto totam. Id voluptatem, tenetur ducimus recusandae nesciunt dolorum ad cum reiciendis, suscipit dolores mollitia et illo? </p> </> ); }
关键细节说明
- 状态控制延迟:通过
skipDelay状态动态切换动画延迟,滚动时设置为0立即触发动画 - 避免重复触发:用
hasTriggeredref标记动画是否已执行,触发后移除滚动监听,防止多次触发 - 元素引用优化:用
useRef获取遮罩元素,替代原生DOM查询,符合React组件的状态管理规范 - 动画完成处理:直接通过ref操作元素样式,更安全可靠
内容的提问来源于stack exchange,提问作者chitzui
相关产品推荐
相关产品推荐

