React 中的动画
介绍
动画是给 Web 应用画龙点睛的一种巧妙方法。作为开发人员,我们经常将动画放在实现的最后阶段,并专注于功能规范。这样做的一个关键原因是动画带来的复杂性。但实际上,大多数动画都只需要几行代码即可实现。一旦添加,动画就会显著改善整个 Web 应用的用户体验,使其更加直观和吸引人。因此,了解至少基本动画的实现技术是有益的。
在本指南中,我们将使用一个简单的选项卡窗格示例来探索动画。我们经常在视图中使用选项卡式导航。在 jQuery 时代,只要导入必要的库,我们的选项卡就可以完美运行。但使用 React,我们需要做更多工作,让用户体验直观且吸引用户。
为了简单起见,我们将使用 Bootstrap 中的选项卡组件。请注意,我们不会使用 React-Bootstrap(它为每个 Bootstrap 组件提供了 React 组件实现),而是使用普通的 Bootstrap CSS 样式。首先,创建一个应用程序,并使用npm install --save bootstrap添加 Bootstrap 。然后我们将添加以下选项卡式组件。
// App.js
import React, { useState } from 'react';
import logo from './logo.svg';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css';
function TabComponent() {
const [currentTab, setCurrentTab] = useState(1);
return (
<div className="tabs">
<ul class="nav nav-tabs">
<li class="nav-item">
<a
class={`nav-link ${currentTab===1 ? 'active' : ''}`}
onClick={() => setCurrentTab(1)} href="#"
>
Tab 01
</a>
</li>
<li class="nav-item">
<a
class={`nav-link ${currentTab===2 ? 'active' : ''}`}
onClick={() => setCurrentTab(2)} href="#"
>
Tab 02
</a>
</li>
<li class="nav-item">
<a
class={`nav-link ${currentTab===3 ? 'active' : ''}`}
onClick={() => setCurrentTab(3)} href="#"
>
Tab 03
</a>
</li>
</ul>
<div class="tab-content">
{currentTab === 1 &&
<div id="home" class="tab-pane">
<h3>Tab 01</h3>
<p>Some content</p>
</div>
}
{currentTab === 2 &&
<div id="menu1" class="tab-pane">
<h3>Tab 02</h3>
<p>Some content</p>
</div>
}
{currentTab === 3 &&
<div id="menu1" class="tab-pane">
<h3>Tab 03</h3>
<p>Some content</p>
</div>
}
</div>
</div>
)
}
function App() {
return (
<div className="App">
<header className="App-header">
<TabComponent />
</header>
</div>
);
}
export default App;
运行应用时,您会发现虽然标签页可以正常工作,但它们的感觉与原生标签页组件不同。理想情况下,单击标签页时,内容应根据标签页的方向滑入,而不是像此处一样突然消失和出现。
使用纯 CSS 制作动画
CSS 过渡是为您的应用引入动画的绝佳起点。鉴于广泛的浏览器支持、硬件渲染能力和易用性,纯 CSS 过渡应该是您实现动画的首选。但您很快就会发现,当与 React 结合使用时,CSS 过渡有一些限制。
CSS 过渡被广泛用于提供悬停和聚焦等用户操作的 UX 反馈。首先,您将通过动画使选项卡导航对用户更直观。一般来说,选项卡的当前趋势是使用活动选项卡底部的彩色边框来表示当前活动的选项卡。相同的样式可以应用于悬停事件。以下代码演示了此示例。
.nav-tabs{
border: none;
}
.nav-tabs .nav-item .nav-link{
border: none;
}
.nav-tabs .nav-item .nav-link.active{
border-bottom: 3px solid #E40046;
}
.nav-tabs .nav-item .nav-link:hover{
border-bottom: 3px solid #E40046;
}
.tab-content{
padding: 10px;
}
.tab-pane{
display: block;
}
虽然它可以响应用户的悬停操作,但响应并不直观或流畅。它缺乏适当动画的质量。为了克服这个问题,您可以尝试以下简单的过渡并查看体验的变化。
.nav-tabs{
border: none;
}
.nav-tabs .nav-item .nav-link{
border: none;
position: relative;
}
.nav-tabs .nav-item .nav-link::before{
content: '';
position: absolute;
width:0;
height:3px;
background:#E40046;
position:absolute;
left: 50%;
bottom: -3px;
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
.nav-tabs .nav-item .nav-link.active{
border-bottom: 3px solid #E40046;
}
.nav-tabs .nav-item .nav-link:hover::before{
left: 0;
width: 100%;
}
.nav-tabs .nav-item .nav-link.active::before{
width: 0;
}
.tab-content{
padding: 10px;
}
.tab-pane{
display: block;
}
显然,即使进行简单的调整,用户体验也会得到显著改善。接下来,重点是选项卡内容。如前所述,理想的情况是当用户更改活动选项卡时滑动选项卡内容。您可以尝试通过定义活动类并将其分配给活动选项卡,将上述 CSS 调整扩展到选项卡内容。
.nav-tabs{
border: none;
}
.nav-tabs .nav-item .nav-link{
border: none;
position: relative;
}
.nav-tabs .nav-item .nav-link::before{
content: '';
position: absolute;
width:0;
height:3px;
background:#E40046;
position:absolute;
left: 50%;
bottom: -3px;
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
.nav-tabs .nav-item .nav-link.active{
border-bottom: 3px solid #E40046;
}
.nav-tabs .nav-item .nav-link:hover::before{
left: 0;
width: 100%;
}
.nav-tabs .nav-item .nav-link.active::before{
width: 0;
}
.tab-content{
padding: 10px;
}
.tab-pane{
display: block;
position: relative;
left: 100%;
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
.tab-pane.active{
left: 0;
}
function TabComponent() {
const [currentTab, setCurrentTab] = useState(1);
return (
<div className="tabs">
<ul class="nav nav-tabs">
<li class="nav-item">
<a
class={`nav-link ${currentTab===1 ? 'active' : ''}`}
onClick={() => setCurrentTab(1)} href="#"
>
Tab 01
</a>
</li>
<li class="nav-item">
<a
class={`nav-link ${currentTab===2 ? 'active' : ''}`}
onClick={() => setCurrentTab(2)} href="#"
>
Tab 02
</a>
</li>
<li class="nav-item">
<a
class={`nav-link ${currentTab===3 ? 'active' : ''}`}
onClick={() => setCurrentTab(3)} href="#"
>
Tab 03
</a>
</li>
</ul>
<div class="tab-content">
{currentTab === 1 &&
<div class={`tab-pane ${currentTab===1 ? 'active' : ''}`}>
<h3>Tab 01</h3>
<p>Some content</p>
</div>
}
{currentTab === 2 &&
<div class={`tab-pane ${currentTab===2 ? 'active' : ''}`}>
<h3>Tab 02</h3>
<p>Some content</p>
</div>
}
{currentTab === 3 &&
<div class={`tab-pane ${currentTab===3 ? 'active' : ''}`}>
<h3>Tab 03</h3>
<p>Some content</p>
</div>
}
</div>
</div>
)
}
运行上述代码时,您会发现选项卡只是简单地出现,而不是按预期进行动画处理。原因在于 DOM 的行为方式。在前面的例子中,当触发悬停事件时,DOM 元素没有发生变化。因此,浏览器按预期呈现了动画。但在这种情况下,新选项卡内容最初并不存在于 DOM 中。它是使用 React 条件渲染显示在 DOM 中的。因此,浏览器只是跳过动画并直接显示新添加的内容。这个问题需要外部库的支持才能提供所需的效果。
使用 ReactTransitionGroup 进行动画处理
有多个成熟的库可用于支持 React 中的动画,例如:
本指南将使用ReactTransitionGroup ,因为它是React推荐的事实库。但这些技巧可以轻松应用于其他库。首先,使用npm install react-transition-group@1.x --save安装它。
以下代码展示了如何使用ReactTransitionGroup实现滑入效果。它涉及使用ReactCSSTransitionGroup包装您的 React 组件并使用 CSS 指定所需的效果。这使您可以在将 CSS 过渡应用于 React 时利用其强大功能。
import { CSSTransitionGroup } from 'react-transition-group'
function TabComponent() {
const [currentTab, setCurrentTab] = useState(1);
return (
<div className="tabs">
<ul class="nav nav-tabs">
<li class="nav-item">
<a
class={`nav-link ${currentTab===1 ? 'active' : ''}`}
onClick={() => setCurrentTab(1)} href="#"
>
Tab 01
</a>
</li>
<li class="nav-item">
<a
class={`nav-link ${currentTab===2 ? 'active' : ''}`}
onClick={() => setCurrentTab(2)} href="#"
>
Tab 02
</a>
</li>
<li class="nav-item">
<a
class={`nav-link ${currentTab===3 ? 'active' : ''}`}
onClick={() => setCurrentTab(3)} href="#"
>
Tab 03
</a>
</li>
</ul>
<div class="tab-content">
<CSSTransitionGroup
transitionName="slidein"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}
>
{currentTab === 1 &&
<div class={`tab-pane ${currentTab===1 ? 'active' : ''}`}>
<h3>Tab 01</h3>
<p>Some content</p>
</div>
}
{currentTab === 2 &&
<div class={`tab-pane ${currentTab===2 ? 'active' : ''}`}>
<h3>Tab 02</h3>
<p>Some content</p>
</div>
}
{currentTab === 3 &&
<div class={`tab-pane ${currentTab===3 ? 'active' : ''}`}>
<h3>Tab 03</h3>
<p>Some content</p>
</div>
}
</CSSTransitionGroup>
</div>
</div>
)
}
.nav-tabs{
border: none;
}
.nav-tabs .nav-item .nav-link{
border: none;
position: relative;
}
.nav-tabs .nav-item .nav-link::before{
content: '';
position: absolute;
width:0;
height:3px;
background:#E40046;
position:absolute;
left: 50%;
bottom: -3px;
-webkit-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
}
.nav-tabs .nav-item .nav-link.active{
border-bottom: 3px solid #E40046;
}
.nav-tabs .nav-item .nav-link:hover::before{
left: 0;
width: 100%;
}
.nav-tabs .nav-item .nav-link.active::before{
width: 0;
}
.tab-content{
padding: 10px;
}
.tab-pane{
display: block;
position: relative;
}
.slidein-enter {
left: 100%;
transition: all 0.3s ease-out;
}
<span class="hljs-s
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~