React动画实现方案之 Framer Motion,让你的页面“自己”动起来( 二 )

展示(mount)隐藏(unmount):
import * as React from "react";import { useRef } from "react";import { motion, useCycle } from "framer-motion";import { useDimensions } from "./use-dimensions";const sidebar = {open: (height = 1000) => ({clipPath: `circle(${height * 2 + 200}px at 40px 40px)`,transition: {type: "spring",stiffness: 20,restDelta: 2}}),closed: {clipPath: "circle(30px at 40px 40px)",transition: {delay: 0.5,type: "spring",stiffness: 400,damping: 40}}};export const Example = () => {const [isOpen, toggleOpen] = useCycle(false, true);const containerRef = useRef(null);const { height } = useDimensions(containerRef);return (<motion.navinitial={false}animate={isOpen ? "open" : "closed"}custom={height}ref={containerRef}><motion.div className="background" variants={sidebar} /><MenuToggle toggle={() => toggleOpen()} /></motion.nav>);};也就是说,其实我们更多需要做的事情,从思考如何设计各元素之间的css联动与keyframe书写变成了如何按照文档写好framer-motion的配置 。哪个更轻松相信大家一目了然 。
列表侧边栏一般都是带有菜单的,那么我们是不是可以让这个侧边栏也有一个逐次出现的效果呢?就像这样:

React动画实现方案之 Framer Motion,让你的页面“自己”动起来

文章插图
这里我们是不是已经开始肌肉记忆般的计算延迟时间,思考如何进行整体效果的分配 。那么如果这里我们使用frame motion,它的实现方式应该是怎么样的呢?
首先我们先来进行单个Item的封装:
import * as React from "react";import { motion } from "framer-motion";const variants = {open: {y: 0,opacity: 1,transition: {y: { stiffness: 1000, velocity: -100 }}},closed: {y: 50,opacity: 0,transition: {y: { stiffness: 1000 }}}};const colors = ["#FF008C", "#D309E1", "#9C1AFF", "#7700FF", "#4400FF"];export const MenuItem = ({ i }) => {const style = { border: `2px solid ${colors[i]}` };return (<motion.livariants={variants}whileHover={{ scale: 1.1 }}whileTap={{ scale: 0.95 }}><div className="icon-placeholder" style={style} /><div className="text-placeholder" style={style} /></motion.li>);};然后我们在已封装Item的基础上,再进行整个菜单的封装:
import * as React from "react";import { motion } from "framer-motion";const itemIds = [0, 1, 2, 3, 4];const variants = {open: {transition: { staggerChildren: 0.07, delayChildren: 0.2 }},closed: {transition: { staggerChildren: 0.05, staggerDirection: -1 }}};export const Navigation = () => (<motion.ul variants={variants}>{itemIds.map(i => (<MenuItem i={i} key={i} />))}</motion.ul>);没错,动画!就是这么简单!
更多API更详细、更具体的功能大家可以参考下官方的使用文档,我就不在这里一一列举了 。
美中不足其实不难看出,不论是实现的效果,还是使用方式,对于前端的同学来说framer-motion都是非常友好的工具 。这一点从npm的Weekly Downloads以及github的star上面都不难看出 。
React动画实现方案之 Framer Motion,让你的页面“自己”动起来

文章插图

React动画实现方案之 Framer Motion,让你的页面“自己”动起来

文章插图
但是目前也有一个问题,那就是包的体积问题 。
React动画实现方案之 Framer Motion,让你的页面“自己”动起来

文章插图
这个包的大小对于部分的系统来说,还是不够友好 。这也是很多人不选择使用它的原因 。

经验总结扩展阅读