React中使用Framer Motion实现allhero.co.jp同款页面过渡动画
React + Framer Motion 页面过渡实现方案
现有代码问题修正
原有代码存在三处基础问题需要先修复:
- 动画配置语法错误:
transition: { duration: 0.5, {delay:0.3} }属于对象嵌套错误,需改为transition: { duration: 0.5, delay: 0.3 } - 缺少退场动画配置,仅实现了入场效果,没有加载完成后遮罩消失的逻辑
- 未做组件封装,无法直接复用
可复用组件完整实现
样式代码(SCSS)
.anim-page{ &,._red{ position: fixed; top: 0; left: 0; width: 100%; height: 100vh; z-index:999; } &._black{ background-color: #000; /* 退场后不拦截页面交互 */ pointer-events: none; } ._red{ background-color: #ff0000; } }
封装过渡组件
import { motion, AnimatePresence } from 'framer-motion'; import { useEffect, useState } from 'react'; const pageAnim = { red: { hidden: { scaleX: 0 }, visible: { scaleX: [1, 0], transformOrigin: 'right', transition: { duration: 0.5, delay: 0.3, ease: [0.22, 1, 0.36, 1] }, }, exit: { scaleX: 1, transformOrigin: 'left', transition: { duration: 0.4 } } }, black: { hidden: { x: '100%', skewX: '-25deg' }, visible: { x: '0%', skewX: '0deg', transition: { duration: 0.7, ease: [0.22, 1, 0.36, 1] }, }, exit: { x: '-100%', skewX: '-25deg', transition: { duration: 0.6, delay: 0.2, ease: [0.22, 1, 0.36, 1] } } }, } // 可复用页面过渡组件 const PageTransition = ({ customLoading = null }) => { // 默认监听页面加载完成,也可传入自定义加载状态 const [isLoading, setIsLoading] = useState(true); useEffect(() => { if (customLoading !== null) { setIsLoading(customLoading); return; } // 默认页面资源加载完成自动触发退场 window.addEventListener('load', () => { setIsLoading(false); }); return () => window.removeEventListener('load', () => setIsLoading(false)); }, [customLoading]); return ( <AnimatePresence> {isLoading && ( <motion.div className='anim-page _black' variants={pageAnim.black} initial='hidden' animate='visible' exit='exit' key='transition-black' > <motion.div className='_red' variants={pageAnim.red} key='transition-red' /> </motion.div> )} </AnimatePresence> ); }; export default PageTransition;
组件使用方式
- 页面加载时自动触发:直接在根组件/App组件内引入使用即可,页面资源加载完成后会自动退场
import PageTransition from './components/PageTransition'; function App() { return ( <div className="App"> <PageTransition /> {/* 其他页面内容 */} </div> ); }
- 绑定自定义加载状态(比如页面接口请求完成后再退场):
const HomePage = () => { const [dataLoading, setDataLoading] = useState(true); useEffect(() => { // 模拟接口请求 fetch('/api/pageData').then(res => res.json()).then(() => { setDataLoading(false); }); }, []); return ( <div> <PageTransition customLoading={dataLoading} /> {/* 页面内容 */} </div> ); };
效果优化建议
如果需要更贴近目标站点的过渡效果,可调整以下参数:
- 修改黑色层、红色层的背景色匹配目标站点的色值
- 调整动画的
duration、delay参数匹配目标站点的动画节奏 - 如果是路由切换场景的过渡,可将组件放在路由配置外层,监听路由变化触发
isLoading状态切换即可实现页面跳转时的过渡效果
内容的提问来源于stack exchange,提问作者A.Anvarbekov
相关产品推荐
相关产品推荐

