ReactJS - 动画
ReactJS - 动画
Section titled “ReactJS - 动画”动画可以通过使 UI 过渡更平滑、更直观来显著提升用户体验。React 本身没有内置的动画系统,但它提供了 Hook 并能很好地与第三方动画库集成。react-transition-group 是一个管理 CSS 过渡和动画的流行选择。
本章将演示如何使用 react-transition-group 创建基本动画。
步骤 1 - 安装 react-transition-group
Section titled “步骤 1 - 安装 react-transition-group”react-transition-group 是一个库,它暴露了一些组件用于管理过渡阶段,从而更容易在组件进入或离开 DOM 时实现动画。
使用 npm 或 yarn 安装它:
your-project-directory> npm install react-transition-groupyour-project-directory> yarn add react-transition-group步骤 2 - 添加 CSS 文件
Section titled “步骤 2 - 添加 CSS 文件”使用 react-transition-group 实现动画依赖于 CSS 过渡或动画。创建一个 CSS 文件(例如,在 src 文件夹中的 animations.css),并将其导入到你的组件或主应用程序文件中。
示例:src/animations.css(我们稍后会填充内容)
并在 App.js 或 main.js 中导入它:
import './animations.css'; // Adjust path as necessary步骤 3 - 出现动画(CSSTransition)
Section titled “步骤 3 - 出现动画(CSSTransition)”react-transition-group 中的 CSSTransition 组件有助于在单个组件首次挂载或其 in prop 改变时为其添加动画。
让我们创建一个在出现时淡入的组件。
src/App.jsx
Section titled “src/App.jsx”import React, { useState, useEffect } from 'react';import { CSSTransition } from 'react-transition-group';import './animations.css'; // Make sure to create and import this CSS file
function App() { const [showTitle, setShowTitle] = useState(false);
// Trigger the animation after the component mounts useEffect(() => { setShowTitle(true); }, []);
return ( <div> <CSSTransition in={showTitle} // Controls the transition (true to enter, false to exit) timeout={500} // Duration of the transition in milliseconds classNames="fade" // Prefix for CSS classes (e.g., fade-enter, fade-enter-active) appear // Enable appear transition on initial mount unmountOnExit // Optional: remove the component from DOM when exited > <h1>My Animated Element</h1> </CSSTransition> </div> );}
export default App;src/main.js (或 src/index.js)
Section titled “src/main.js (或 src/index.js)”import React from 'react';import ReactDOM from 'react-dom/client';import App from './App.jsx';
const root = ReactDOM.createRoot(document.getElementById('root'));root.render( <React.StrictMode> <App /> </React.StrictMode>);src/animations.css (用于出现动画)
Section titled “src/animations.css (用于出现动画)”/* Fade Appear Animation */.fade-appear { opacity: 0;}.fade-appear-active { opacity: 1; transition: opacity 500ms ease-in;}
/* If you also want enter/exit animations for dynamic show/hide later */.fade-enter { opacity: 0;}.fade-enter-active { opacity: 1; transition: opacity 500ms ease-in;}.fade-exit { opacity: 1;}.fade-exit-active { opacity: 0; transition: opacity 500ms ease-in;}解释:
-
我们使用
useState和useEffect在组件挂载后将showTitle设置为true,从而触发CSSTransition的inprop。 -
CSSTransition的 prop:in:布尔值。当为true时,应用进入/出现类。当为false时,应用退出类。timeout:动画持续时间(毫秒)。应与你的 CSS 过渡持续时间匹配。classNames:一个字符串前缀。react-transition-group会附加后缀,如-appear、-appear-active、-enter、-enter-active、-exit、-exit-active。appear:在初始挂载时启用出现过渡,使用*-appear和*-appear-active类。unmountOnExit:如果为 true,组件在完成退出后将从 DOM 中移除。
当应用程序加载时,<h1> 元素将淡入。
步骤 4 - 进入和离开动画(TransitionGroup)
Section titled “步骤 4 - 进入和离开动画(TransitionGroup)”要对列表项(例如,添加或移除项时)进行动画处理,请结合使用 TransitionGroup 和 CSSTransition 组件。
src/App.jsx (用于列表动画)
Section titled “src/App.jsx (用于列表动画)”import React, { useState } from 'react';import { CSSTransition, TransitionGroup } from 'react-transition-group';import './animations.css'; // Ensure this CSS file includes .item-* classesimport { v4 as uuidv4 } from 'uuid'; // For unique keys: npm install uuid
function App() { const [items, setItems] = useState([ { id: uuidv4(), text: 'Item 1...' }, { id: uuidv4(), text: 'Item 2...' }, ]);
const handleAddItem = () => { const newItemText = prompt('Enter new item text:'); if (newItemText) { setItems(prevItems => [ ...prevItems, { id: uuidv4(), text: newItemText }, ]); } };
const handleRemoveItem = (idToRemove) => { setItems(prevItems => prevItems.filter(item => item.id !== idToRemove)); };
return ( <div> <button onClick={handleAddItem}>Add Item</button> <TransitionGroup component="ul"> {/* component prop defines the wrapping element */} {items.map(({ id, text }) => ( <CSSTransition key={id} // Crucial: unique key for each item timeout={500} classNames="item" > <li onClick={() => handleRemoveItem(id)}> {text} </li> </CSSTransition> ))} </TransitionGroup> </div> );}
export default App;src/animations.css (列表动画的补充)
Section titled “src/animations.css (列表动画的补充)”/* ... (keep .fade-* classes from above if needed) ... */
/* Item Enter/Exit Animation */.item-enter { opacity: 0; transform: translateX(-100px);}.item-enter-active { opacity: 1; transform: translateX(0); transition: opacity 500ms ease-in, transform 500ms ease-in;}.item-exit { opacity: 1; transform: translateX(0);}.item-exit-active { opacity: 0; transform: translateX(100px); transition: opacity 500ms ease-in, transform 500ms ease-in;}列表动画解释:
-
我们使用
uuid为列表项生成唯一的 ID,这对于TransitionGroup正确跟踪项至关重要。通过npm install uuid安装它。 -
TransitionGroup:包装多个CSSTransition组件。它监控其子项。当添加或移除子项时,TransitionGroup管理其动画状态。 -
CSSTransition(在map内部):每个列表项都包裹在自己的CSSTransition中。keyprop 必须是唯一的且稳定的,对于每个项都是如此。classNames设置为"item",因此将应用像item-enter、item-enter-active等 CSS 类。
-
handleAdd和handleRemove:这些函数更新items状态。React 重新渲染,TransitionGroup检测到其子项的变化,触发动画。
当你添加一个项时,它将动画进入(从左侧滑入并淡入)。当你点击一个项将其移除时,它将动画退出(向右侧滑出并淡出)。
关于 prompt() 的注意:在演示中使用 prompt() 很简单,但由于其阻塞特性和浏览器样式不一致,通常不建议在生产 UI 中使用。在实际应用中,你会在 React 组件内部使用适当的输入字段。
进一步探索:
react-transition-group 还提供了 Transition 和 SwitchTransition 组件,用于更精细的控制。对于更复杂的基于物理的动画或交互,像 Framer Motion (https://www.framer.com/motion/) 或 React Spring (https://www.react-spring.dev/) 这样的库是极好的选择。请务必参考这些库的官方文档以获取最新信息和高级功能。