我有一个物品清单。当我第一次加载页面时,我希望它们快速连续地按顺序滑入,然后在到达最终目的地时略微收缩——有点像如果你丢下一堆枕头会发生什么,或者 一大堆切片熟肉。 (我以前看过这个动画,但找不到例子,也不知道它叫什么;如果有人能找到例子的链接,请贴出来。)
这是我非常初级的尝试:
import {Button, Slide, Stack, StackProps} from '@mui/material'
import {Box} from '@mui/system'
interface ZoomStackProps extends PropsWithChildren<StackProps> {
timeout: number
}
export default function SquishSlideStack({children, timeout, ...stackProps}: ZoomStackProps) {
const [mountIndex, setMountIndex] = useState(0)
const [squozeIndex, setSquozeIndex] = useState(0)
function increment(n: number) {
if (n < React.Children.count(children) - 1) {
setMountIndex(n)
setTimeout(() => increment(n + 1), timeout)
}
}
useEffect(() => increment(1), [])
return (
<Stack {...stackProps}>
<Button onClick={() => setMountIndex(index => index + 1)}>Next</Button>
{React.Children.map(children, (child, i) =>
i > mountIndex ? (
null
) : (
<Slide
key={i}
in={true}
direction='up'
timeout={1000}
addEndListener={() => setSquozeIndex(i)}
>
<Box bgcolor='green'
width={600}
height={50}
sx={{
transform: i > squozeIndex ? 'scale(1, 1.5)' : 'scale(1, 1)',
transition: 'transform 2s ease'
}}
>
{child}
</Box>
</Slide>
)
)}
</Stack>
)
}
这里的滑动部分或多或少起作用,但只有当我关闭挤压/缩放部分时。由于某种原因,添加它会破坏滑动并且也无法正确缩放。
在 React 中(希望在 MUI 中实现这样的动画,尽管这不是必需的)最好的方法是什么?
最好的实现方式是CSS3动画。
如果你需要任何关于 React 和 MUI 实现方面的帮助,请评论。
这里是一个简单的Demo,您可能需要根据需要更改动画中translate3d和scaleY的参数。
<h1 class="callout-title_first animate__animated">Animate.css</h1>
<h1 class="callout-title_bottom animate__animated">Animate.css</h1>
<style>
h1 {
margin:0;
}
@keyframes slideInDown_first {
0%{
transform: translate3d(0,-100%,0);
}
33%{
transform: translate3d(0,50%,0) ;
}
40%{
transform-origin: bottom;;
transform: translate3d(0,50%,0) scaleY(0.5);
}
to{
transform: scaleY(0.5) translate3d(0,100%,0);
}
}
@keyframes slideInDown_second {
0%{
transform: translate3d(0,-100%,0);
}
33%{
transform: translate3d(0,0,0) ;
}
40%{
transform-origin: bottom;;
transform: translate3d(0,0,0) scaleY(0.5);
}
66%{
transform: translate3d(0,-20%,0) scaleY(0.5);
}
to{
transform: translateZ(0);
transform: scaleY(0.5);
}
}
.animate__slideInDown_first {
animation-name: slideInDown_first
}
.animate__slideInDown_second {
animation-name: slideInDown_second
}
.animate__animated {
animation-duration: 3000ms;
animation-fill-mode: both
}
</style>
<script>
document.querySelector('.callout-title_first').classList.add('animate__slideInDown_first')
document.querySelector('.callout-title_bottom').classList.add('animate__slideInDown_second')
</script>