react中使用过渡动画

官方文档

https://reactcommunity.org/react-transition-group/

安装

cnpm i --save-dev react-transition-group
"react-transition-group": "^4.4.2",

插件中的组件

CSSTransition css过渡组件

分为入场动画和过渡动画

  1. *-enter-active表示想要动画到那些样式

  2. *-exit-active 表示离开之后的动画

属性

classNames属性是在组件进入、退出时应用于组件的动画类名称。每个阶段都会加上后缀,

例如

.fade-enter  入场动画第一帧
.fade-enter-active 入场动画第二帧
.fade-enter-done 入场动画执行完成
.fade-exit 出场动画第一帧
.fade-exit-active 出场动画第二帧
.fade-exit-done 出场动画结束
.fade-appear
.fade-appear-active 功能和入场动画一致  需要添加属性appear={true}  首次渲染时执行动画
​​

import './App.css'
import { useState } from 'react'
//引入过渡动画
import { CSSTransition } from 'react-transition-group'
console.log(CSSTransition);
function App() {
  let [show, setShow] = useState(true);
  let handle = function () {
    setShow(!show);
  }
  return (
    <div className="App">
      <CSSTransition
      in={show}   //显示隐藏
      timeout={1000}  //动画时间
      classNames={'fade'}
      unmountOnExit={true}   //隐藏移除dom
      appear={true} 
      >
        <span>App组件</span>
      </CSSTransition>
​
      <button onClick={handle}>显示隐藏</button>
    </div>
  )
}
​
export default App
​
​
.fade-enter,.fade-appear{
    opacity: 0;
}
.fade-enter-active,.fade-appear-active{
    opacity: 1;
    transition: opacity .5s;
}
.fade-exit{
    opacity: 1;
}
.fade-exit-active{
    opacity: 0;
    transition: opacity .5s;
}
.fade-exit-done{
    opacity: 0;
}
​

如果实现多个标签动画使用动画组

TransitionGroup组件

路由组件实现动画

 <TransitionGroup className='box-animate'>
      <CSSTransition classNames={"fade"} timeout={1000} key={location.pathname} >
        <Switch location={location}>
          <Route path="/about" >
            <About />
          </Route>
          <Route path="/users">
            <User />
          </Route>
          <Route path="/">
            <Home />
          </Route>
        </Switch>
      </CSSTransition>
    </TransitionGroup>
.fade-enter {
  opacity: 0;
  transform: translateX(100%);
}
​
.fade-enter-active {
  opacity: 1;
  transform: translateX(0);
  transition: all 500ms;
}
​
.fade-exit {
  opacity: 1;
  transform: translateX(0);
}
​
.fade-exit-active {
  opacity: 0;
  transform: translateX(-100%);
  transition: all 500ms;
}

如何实现路由组件根据路由的进入和离开 控制动画

childFactory
您可能需要在孩子退出时对其应用响应式更新。这通常是通过使用来完成的,cloneElement但是在现有子元素的情况下,该元素已被删除并且消费者无法访问。
​
如果您确实需要在孩子离开时对其进行更新,您可以提供一个childFactory 来包装每个孩子,即使是那些正在离开的孩子。
​
类型:Function(child: ReactElement) -> ReactElement
默认:child => child

多个动画切换

// src/App6/RouteConfig.js
export const RouterConfig = [
  {
    path: '/',
    component: HomePage
  },
  {
    path: '/about',
    component: AboutPage,
    sceneConfig: {
      enter: 'from-bottom',
      exit: 'to-bottom'
    }
  },
  {
    path: '/list',
    component: ListPage,
    sceneConfig: {
      enter: 'from-right',
      exit: 'to-right'
    }
  },
  {
    path: '/detail',
    component: DetailPage,
    sceneConfig: {
      enter: 'from-right',
      exit: 'to-right'
    }
  }
];

index.js

// src/App6/index.js
const DEFAULT_SCENE_CONFIG = {
  enter: 'from-right',
  exit: 'to-exit'
};
​
const getSceneConfig = location => {
  const matchedRoute = RouterConfig.find(config => new RegExp(`^${config.path}$`).test(location.pathname));
  return (matchedRoute && matchedRoute.sceneConfig) || DEFAULT_SCENE_CONFIG;
};
​
let oldLocation = null;
const Routes = withRouter(({location, history}) => {
​
  // 转场动画应该都是采用当前页面的sceneConfig,所以:
  // push操作时,用新location匹配的路由sceneConfig
  // pop操作时,用旧location匹配的路由sceneConfig
  let classNames = '';
  if(history.action === 'PUSH') {
    classNames = 'forward-' + getSceneConfig(location).enter;
  } else if(history.action === 'POP' && oldLocation) {
    classNames = 'back-' + getSceneConfig(oldLocation).exit;
  }
​
  // 更新旧location
  oldLocation = location;
​
  return (
    <TransitionGroup
      className={'router-wrapper'}
      childFactory={child => React.cloneElement(child, {classNames})}
    >
      <CSSTransition timeout={500} key={location.pathname}>
        <Switch location={location}>
          {RouterConfig.map((config, index) => (
            <Route exact key={index} {...config}/>
          ))}
        </Switch>
      </CSSTransition>
    </TransitionGroup>
  );
});
vite工具配置@

export default defineConfig({
  plugins: [react()],
  resolve:{
    alias:{
      "@":resolve('src')
    }
  }
})
​

react原生项目中配置@

安装@craco/craco

在src同级目录创建文件

// src/App6/index.js
const DEFAULT_SCENE_CONFIG = {
  enter: 'from-right',
  exit: 'to-exit'
};
​
const getSceneConfig = location => {
  const matchedRoute = RouterConfig.find(config => new RegExp(`^${config.path}$`).test(location.pathname));
  return (matchedRoute && matchedRoute.sceneConfig) || DEFAULT_SCENE_CONFIG;
};
​
let oldLocation = null;
const Routes = withRouter(({location, history}) => {
​
  // 转场动画应该都是采用当前页面的sceneConfig,所以:
  // push操作时,用新location匹配的路由sceneConfig
  // pop操作时,用旧location匹配的路由sceneConfig
  let classNames = '';
  if(history.action === 'PUSH') {
    classNames = 'forward-' + getSceneConfig(location).enter;
  } else if(history.action === 'POP' && oldLocation) {
    classNames = 'back-' + getSceneConfig(oldLocation).exit;
  }
​
  // 更新旧location
  oldLocation = location;
​
  return (
    <TransitionGroup
      className={'router-wrapper'}
      childFactory={child => React.cloneElement(child, {classNames})}
    >
      <CSSTransition timeout={500} key={location.pathname}>
        <Switch location={location}>
          {RouterConfig.map((config, index) => (
            <Route exact key={index} {...config}/>
          ))}
        </Switch>
      </CSSTransition>
    </TransitionGroup>
  );
});
vite工具配置@

export default defineConfig({
  plugins: [react()],
  resolve:{
    alias:{
      "@":resolve('src')
    }
  }
})
​

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值