将 MUI 与 React 结合使用时,我们可以为页面中的组件设置折叠(Collapse)、淡入淡出(Fade)、拓展(Grow)以及滑动(Slide)在内的多种不同的动画效果。在本文中,我们通过多个组件的淡入淡出效果组合,来实现近似渐变的动画效果。
淡入淡出效果
MUI 基于底层的 react-transition-group 组件对几种常用动画效果进行了封装,比如 MUI 官方文档中提到的淡入淡出动画效果:
对应的代码如下:
// ...
export default function SimpleFade() {
const [checked, setChecked] = React.useState(false);
const handleChange = () => {
setChecked((prev) => !prev);
};
return (
<Box sx={{ height: 180 }}>
<FormControlLabel
control={<Switch checked={checked} onChange={handleChange} />}
label="Show"
/>
<Box sx={{ display: 'flex' }}>
<Fade in={checked}>{icon}</Fade>
<Fade in={!checked}>{icon}</Fade>
</Box>
</Box>
);
}
在上述示例中,我们通过按钮来控制两个 icon 的显示状态。但这里有一个问题,隐藏的 icon 组件也会占有对应的位置,使得在绘制 UI 界面时出现问题:
这里需要注意的地方在于,需要将隐藏的对象设置为条件渲染(conditional rendering),才能使两个对象之间达到正确的“切换”效果:
// ...
<Box sx={{ display: 'flex' }}>
{checked && <Fade in={checked}>{icon}</Fade>}
{!checked && <Fade in={!checked}>{icon}</Fade>}
</Box>
// ...
实际上,使用这种方式实现的切换效果对于要隐藏的元素并没有“消失”效果,只对要切换到的元素添加了“渐入”效果。如果为 Fade 组件设置一个较短的 timeout
时间,则有助于在视觉上减小这种影响。
实际示例
我们以仿照 Google 登录界面为例,展示采用 MUI 中 Fade 效果的类似渐变的切换模式:
在上述示例中,我们使用了 Grid 容器对登录页面的两个状态(登录与注册)进行了管理,对于其中的每个组件(登录组件与注册组件),都设置了持续时长为 600 毫秒的渐入渐出动画效果:
<Grid item style={{ width: "95vw", maxWidth: "440px" }}>
<Paper variant="outlined" style={{
paddingLeft: "40px",
paddingRight: "40px",
paddingTop: "18px",
paddingBottom: "18px",
backgroundColor: "rgba(255, 255, 255, 0.75)" }}>
<Fade in={!wishRegister} timeout={600}>
<Box>{wishRegister === false ? <LoginPageLogin
setUserToken={props.setUserToken}
setWishRegister={setWishRegister}
username={username}
setUsername={setUsername}
password={password}
setPassword={setPassword}
/> : null}</Box>
</Fade>
<Fade in={wishRegister} timeout={600}><Box>
{wishRegister === true ? <LoginPageRegister
setWishRegister={setWishRegister}
username={username}
setUsername={setUsername}
password={password}
setPassword={setPassword}
/> : null}</Box></Fade>
<Box style={{ height: "2vh" }} />
</Paper>
</Grid>
LoginPageLogin
与 LoginPageRegister
是两个包含登录与注册表单的自定义组件。上述示例使用了 Fade 动画组件进行切换,同时,也可以考虑使用 Slide 等动画实现类似的效果。