探索 Framer Motion 高级动画技巧:提升前端设计水平

亦世凡华、 2024-08-18 12:33:01 阅读 77

在现代的网页和应用设计中,动画不仅仅是视觉的点缀,更是用户体验的重要组成部分。它能够使界面更具吸引力,提升交互的流畅性,甚至在不经意间传达品牌的个性和态度。然而,要创造出令人惊叹的动效并不容易——直到有了 Framer Motion。本文将带你深入探索 Framer Motion 的奥秘,掌握其核心概念和实用技巧,助你在界面设计的旅程中走得更远。

Framer Motion:是一个专业的动画和交互效果库,特别设计用于React应用程序的创建,它提供了简单且强大的工具,帮助开发者和设计师轻松地实现复杂的动画效果,从而增强用户界面的视觉吸引力和交互性,通过使用Framer Motion开发者可以轻松地创建各种动画,如过渡动画、交互式元素动画和响应式布局动画,从而提升其应用程序的用户体验,其官方地址为:地址 :

目前Framer Motion需要React 18版本才可以,低版本的react项目是无法使用的,终端执行如下命令安装,如果是项目是升级到React 19的用户可以安装Framer Motion 12 alpha版,它目前可与React 19 RC配合使用,安装命令如下(因为大部分项目还是react18,所以本文就以18版本举例):

<code># react18版本可安装

npm install framer-motion

# react19版本可安装

npm install framer-motion@12.0.0-alpha.0

Framer Motion提供了一个牛逼的组件:<motion />​,该组件可直接将其视为一个普通的HTML或SVG元素,然后我们可以直接为组件设置动画属性的效果,大大增强了动画功能,它可以接受多种属性来定义和控制动画的行为和外观,以下是一些常用的属性及其作用:

1)animate:指定元素的动画状态,可以是一个对象,其中包含要动画化的 CSS 属性及其目标值,也可以是预定义的动画变体(如"whileHover")。

2)initial:定义元素的初始状态,当组件首次渲染时,会从这个状态开始动画到 animate 属性定义的状态。

3)exit:定义元素离开动画的状态,当元素即将从 DOM 中移除时,会执行这个状态的动画。

4)transition:定义动画过渡的时间、缓动函数(如 ease-in-out)、延迟等参数。可以是一个对象,每个属性的变化都可以定义不同的过渡效果。

5)variants:定义不同动画状态的集合,用于组件在不同状态之间切换时使用,可以定义多个状态集合,以便根据应用的逻辑选择不同的变体。

6)whileHover、whileTap等:提供预定义的动画状态,当用户与元素交互时自动触发,例如,whileHover 可以定义鼠标悬停时的动画效果。

7)drag、dragConstraints、dragElastic、dragMomentum:用于支持元素的拖拽行为,drag 表示元素是否可拖拽,dragConstraints 定义拖拽的约束条件,dragElastic 控制拖拽松弛度,dragMomentum 控制惯性效果。

8)layout、layoutId:控制元素布局和布局动画,layout 可以使元素根据其父容器重新布局,layoutId 则用于在不同页面或组件之间保持布局的一致性。

这些属性使得 <motion /> 组件非常灵活,能够满足各种复杂的动画和交互设计需求,怎么使用呢?直接打出下面的例子,通过motion组件设置一个div,然后其设置本身的css样式后,然后给组件motion.div设置动画效果:

最终呈现的效果如下所示:

 

当然<motion />也提供了使用强大的手势识别器扩展React的事件系统,它支持悬停、点击、平移和拖动等操作,非常的酷炫,如下给出代码:

<code>import { motion } from "framer-motion";

import './index.less'

const Motion = () => {

return (

<>

<div className="container">code>

<motion.div

className="box"code>

initial={ { opacity: 0, scale: 0.5 }} // 初始状态

animate={ { opacity: 1, scale: 1 }} // 动画状态

transition={ { duration: 2 }} // 动画过渡时长

whileHover={ { scale: 1.2 }} // 悬浮状态放大1.2倍

whileTap={ { scale: 1.1 }} // 点击状态放大1.1倍

drag="x" // 拖拽code>

dragConstraints={ { left: -100, right: 100 }} // 拖拽约束

>

内容

</motion.div>

</div>

</>

)

};

export default Motion;

上面我们给div设置了hover、tap、drag等效果,这里我们在浏览器看一下,效果非常酷炫呀!

大概的基础演示就这么多,接下来我们开始详细进入到Framer Motion功能性的讲解!

Framer Motion中有多种动画制作方式,这里可根据自身需求的复杂程度进行扩展,那么如何制作动画呢?这里有如下几种方式:

简单过度动画:通过motion组件和animate(动画)与transition(过渡)道具来完成。

<code><motion.div

className="box"code>

animate={ { x: 100 }} // 动画状态

transition={ { ease: "easeOut", duration: 2 }} // 动画过渡方式:easeOut缓动,持续时间2s

>

内容

</motion.div>

当然这两者的搭配也可以实现关键帧动画的效果,其中times是一个与关键帧数组长度相同的数组,其中的数字0和1定义了动画中每个关键帧应该被击中的位置。代码如下:

<motion.div

className="box"code>

animate={ {

scale: [1, 2, 2, 1, 1],

rotate: [0, 0, 180, 180, 0],

borderRadius: ["0%", "0%", "50%", "50%", "0%"]

}}

transition={ {

duration: 2,

ease: "easeInOut",

times: [0, 0.2, 0.5, 0.8, 1],

repeat: Infinity, // 无限循环

repeatDelay: 1 // 重复间隔时间

}}

>

内容

</motion.div>

页面呈现的效果如下所示:

进入退出动画:通过motion组件和initial(进入)与exit(退出)道具来完成。

注意:在React中当组件从树中移除时它会被立即移除,Framer Motion提供了AnimatePresence在执行退出动画时将组件保留在 DOM 中的功能,代码如下:

<code>import { useState } from "react";

import { motion, AnimatePresence } from "framer-motion";

import './index.less'

const Motion = () => {

const [isShow, setIsShow] = useState(true);

return (

<>

<div className="container">code>

<AnimatePresence>

{ isShow && (

<motion.div

className="box"code>

initial={ { opacity: 0, scale: 0.5, color: '#123456' }} // 初始状态

exit={ { color: '#008c8c' }}

animate={ { opacity: 1, scale: 1 }} // 动画状态

transition={ { ease: "easeOut", duration: 2 }} // 动画过渡方式:easeOut缓动,持续时间2s

>

内容

</motion.div>

) }

</AnimatePresence>

<button style={ { width: '100px', height: '30px' }} onClick={() => setIsShow(!isShow)}>显示/隐藏</button>

</div>

</>

)

};

export default Motion;

最终呈现的效果如下所示:

手势动画:Framer Motion具有在手势开始时将动画设置为一组值的快捷方式,例如hover、tap、drag和focusinView等,它目前支持悬停、点击、平移和拖动手势检测,每个手势都有一系列事件监听器,可以将其附加到您的motion组件上。

<code><motion.div

className="box"code>

animate={ { opacity: 1, scale: 1 }} // 动画状态

transition={ { ease: "easeOut", duration: 2 }} // 动画过渡方式:easeOut缓动,持续时间2s

whileHover={ { scale: 1.2, transition: { duration: 2 } }} // 鼠标悬浮时,scale放大为1.2

whileTap={ { scale: 0.8 }} // 鼠标点击时,scale缩小为0.8

drag // 拖拽

dragConstraints={ { left: 0, top: 0 }} // 拖拽约束

dragElastic={0.2} // 拖拽弹性

onDragStart={(event, info) => console.log(info.point.x, info.point.y)}

onDragEnd={(event, info) => console.log(info.point.x, info.point.y)}

>

内容

</motion.div>

呈现的效果如下所示:

动画内容: MotionValue我们可以通过将 a 作为motion组件的子项传递来呈现其当前值。

<code>import { useEffect } from "react";

import { motion, useMotionValue, useTransform, animate } from "framer-motion";

import './index.less'

const Motion = () => {

const count = useMotionValue(0)

const rounded = useTransform(count, latest => Math.round(latest))

useEffect(() => {

const controls = animate(count, 100, { duration: 10 })

return () => controls.stop()

}, [])

return <motion.div className="box">{rounded}</motion.div>code>

};

export default Motion;

最终呈现的效果如下所示:



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。