React动画:点击展开
我们正在制作
我们将制作一个点击后会展开的卡片。示例是一个水平排列的卡片列表,您可以滚动浏览(使用 CSS 实现scroll-snap-type)。当您点击或轻触卡片时,它会展开占据整个屏幕,并阻止滚动。
![]()
![]()
塞思·科克@darth_knoppix
⚠️ 正在制作一个新教程,演示如何使用 Framer Motion 在 React 中实现多个 UI 状态之间的动画效果。
#workinprogress #react #uidesign #react js #framermotion #uianimation2019年11月30日 下午3:48
如果你想观看视频教程,我会详细讲解添加动画和进行调整以获得所需效果的整个过程。
网页动画技巧
在使用 Framer Motion 或其他 React 和 JS 动画库添加动画时,你可能需要修改 HTML 的结构。有时,添加外层 div 元素并为其添加动画可能比直接操作现有元素更容易。如果你发现自己在尝试实现动画时遇到了困难,不妨退一步思考,看看能否找到一个折衷方案。添加外层元素会稍微破坏 HTML 的结构,但可能会使你的动画代码更加简洁。我个人更倾向于使用div元素,因为你添加元素只是为了在代码中进行操作,它不需要具有语义含义。
如何使用 useCycle hook 实现动画
Framer Motion 提供了一些实用的 React Hook,对于我们的点击展开动画,我们可以利用这个useCycleHook 来实现效果。它提供了当前状态以及一个用于切换状态的函数。要构建这个 Hook,需要提供一个参数列表。在本例中,我们可以使用两个对象来分别表示我们需要在两个不同状态之间切换的动画。
const [animate, toggleFocus] = useCycle(
{ height: "25rem", top: "0rem", overflowX: "auto" },
{ height: "100%", top: "-4.4rem", overflowX: "hidden" }
);
状态将从 开始height: "25rem",等等。当我们toggleFocus第一次调用该函数时,状态将变为height: "100%"等等。如果我们继续调用该toggleFocus函数,useCycle它将无限循环地遍历这些状态。
为了实现动画效果,我们使用motion组件并传入我们的animate状态。Motion 会直接处理这些状态,并在属性发生变化时进行动画切换。为了触发动画,我们将使用onTapprop(也是由 motion 提供的component)并将函数传递给它useCycle。
<motion.div
onTap={() => toggleFocus()}
animate={animate}
/>
这个钩子函数之所以如此灵活,是因为它允许我们传递任意数量、任意类型的参数。如果我们需要在多个状态之间线性切换,这个钩子函数就能很好地胜任。循环函数还接受一个索引,因此我们可以以非线性的方式在不同的 UI 状态之间导航。对于我们的动画来说,只需要两个状态,但如果想要控制多个状态,也可以提供更复杂的对象。
这是演示中使用的一个钩子函数的片段useCycle。使用复杂对象可以让屏幕上多个元素的状态和动画在cycleCard调用时同步变化。
const [animate, cycleCard] = useCycle(
{
card: { padding: "1rem" },
image: {
width: "100%",
marginLeft: "0rem",
marginRight: "0rem",
marginTop: "0rem"
}
},
{
card: { padding: "0rem" },
image: {
width: "125%",
marginLeft: "-3rem",
marginRight: "-3rem",
marginTop: "-1rem"
}
}
);
接下来该怎么办?
在演示中,我们在展开和折叠两种不同的状态之间切换。为了简化代码,可以将这些状态拆分成变体(如“使用 Framer Motion 实现简单的加载动画”一文中所述)。我建议您尝试使用useCycle钩子函数,以便清晰地定义 UI 需要呈现的不同状态。它易于设置和理解,同时又是一个非常强大的动画控制系统。
资源
- 要查看完整源代码,请访问 GitHub 上的代码仓库。
- 欢迎观看我的Framer Motion 动画制作视频教程播放列表。
- 请查看Framer Motion 的官方文档。