You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

组件使用方式

  1. 页面加载时自动触发:直接在根组件/App组件内引入使用即可,页面资源加载完成后会自动退场
import PageTransition from './components/PageTransition';

function App() {
  return (
    <div className="App">
      <PageTransition />
      {/* 其他页面内容 */}
    </div>
  );
}
  1. 绑定自定义加载状态(比如页面接口请求完成后再退场):
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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 06:45:04