前言相信很多前端同学都或多或少和动画
打过交道 。有的时候是产品想要的过度效果
;有的时候是UI想要的酷炫动画
。但是有没有人考虑过,是不是我们的页面上面的每一次变化,都可以像是自然而然的变化;是不是每一次用户点击所产生的交互,都可以在页面上活过来呢?
欢迎你打开了新的前端动画世界——《Framer Motion》
效果体验这里,我在framer官网上面给大家录制了一下大概的使用效果 。
文章插图
在我们的常规认知中,实现这样的效果其实需要很多的css来实现,或者说需要我们进行大量的
定制化逻辑
编写 。但是如果我们使用framer motion
的话,只需要如下代码:import { AnimatePresence, motion } from 'framer-motion';const [selectedId, setSelectedId] = useState(null);{items.map(item => (<motion.div layoutId={item.id} onClick={() => setSelectedId(item.id)}><motion.h5>{item.subtitle}</motion.h5><motion.h2>{item.title}</motion.h2></motion.div>))}<AnimatePresence>{selectedId && (<motion.div layoutId={selectedId}><motion.h5>{item.subtitle}</motion.h5><motion.h2>{item.title}</motion.h2><motion.button onClick={() => setSelectedId(null)} /></motion.div>)}</AnimatePresence>
从上面的实现我们可以看出,framer-motion可以说是我们在用react动效开发过程中的必备利器
。那么接下来 , 我给大家简单介绍一些framer motion的基础用法 。快速开始Framer Motion 需要 React 18 或更高版本 。
安装从npm安装
framer-motion
npm install framer-motion
输入安装后,您可以通过framer-motion
引入Framer Motionimport { motion } from "framer-motion"export const MyComponent = ({ isVisible }) => (<motion.div animate={{ opacity: isVisible ? 1 : 0 }} />)
使用方式Framer motion
的核心API是motion
的组件 。每个HTML
和SVG
标签都有对应的motion
组件 。他们渲染的结果与对应的原生组件完全一致,并在其之上增加了一些动画和手势相关的
props
。比如:
<motion.div /><motion.span /><motion.h1 /><motion.svg />...
示例比如我们现在想要实现一个侧边栏效果 。节点的挂载与卸载(mount、unmount)
文章插图
如果我们自己来实现的话,可能要考虑它的
keyframe
,它的初始状态
与最终的css样式
。那么如果用framer-motion
来如何实现呢?首先我们来设计一个
会动
的按钮Icon:import * as React from "react";import { motion } from "framer-motion";const Path = props => (<motion.pathfill="transparent"strokeWidth="3"stroke="hsl(0, 0%, 18%)"strokeLinecap="round"{...props}/>);const MenuToggle = ({ toggle }) => (<button onClick={toggle}><svg width="23" height="23" viewBox="0 0 23 23"><Pathvariants={{closed: { d: "M 2 2.5 L 20 2.5" },open: { d: "M 3 16.5 L 17 2.5" }}}/><Pathd="M 2 9.423 L 20 9.423"variants={{closed: { opacity: 1 },open: { opacity: 0 }}}transition={{ duration: 0.1 }}/><Pathvariants={{closed: { d: "M 2 16.346 L 20 16.346" },open: { d: "M 3 2.5 L 17 16.346" }}}/></svg></button>);
接下来,就由这个按钮来控制侧边栏的展示(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的配置
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- AR人体姿态识别,实现无边界的人机交互
- 17 基于SqlSugar的开发框架循序渐进介绍-- 基于CSRedis实现缓存的处理
- SpringBoot自定义注解+异步+观察者模式实现业务日志保存
- 支付宝怎样实现银行卡之间转账(如何利用支付宝进行银行卡转账)
- Eureka Server 实现在线扩容
- React实现一个简易版Swiper
- React +SpreadJS+Echarts 项目实战:在线报价采购系统
- 四十七 SpringCloud微服务实战——搭建企业级开发框架:【移动开发】整合uni-app搭建移动端快速开发框架-添加Axios并实现登录功能
- 二 京东云开发者| Redis数据结构-List、Hash、Set及Sorted Set的结构实现
- 一 Redis数据结构-Redis的数据存储及String类型的实现