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

在现代的网页和应用设计中,动画不仅仅是视觉的点缀,更是用户体验的重要组成部分。它能够使界面更具吸引力,提升交互的流畅性,甚至在不经意间传达品牌的个性和态度。然而,要创造出令人惊叹的动效并不容易——直到有了 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版本举例):

# 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的事件系统,它支持悬停、点击、平移和拖动等操作,非常的酷炫,如下给出代码:

import { motion } from "framer-motion";
import './index.less'

const Motion = () => {
  return (
    <>
      <div className="container">
        <motion.div
            className="box"
            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" // 拖拽
            dragConstraints={{ left: -100, right: 100 }} // 拖拽约束
        >
          内容
        </motion.div>
      </div>
    </>
  )
};
export default Motion;

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

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

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

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

<motion.div
    className="box"
    animate={{ x: 100 }} // 动画状态
    transition={{ ease: "easeOut", duration: 2 }} // 动画过渡方式:easeOut缓动,持续时间2s
>
  内容
</motion.div>

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

<motion.div
    className="box"
    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 中的功能,代码如下:

import { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import './index.less'

const Motion = () => {
  const [isShow, setIsShow] = useState(true);
  return (
    <>
      <div className="container">
        <AnimatePresence>
          { isShow && (
            <motion.div
                className="box"
                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组件上。

<motion.div
    className="box"
    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组件的子项传递来呈现其当前值。

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>
};
export default Motion;

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/843071.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Edge侧边栏copilot消失

Edge侧边栏copilot消失 当前环境 自己ip问题已解决&#xff0c;edge中已登录账号&#xff0c;地区已设置为美国&#xff0c;语言已设置为英文。具体可以通过空白页右上角的setting验证 解决方案 首先&#xff0c;打开“任务管理器”&#xff0c;在其中找到 Microsoft Edge…

【SASS/SCSS(三)】样式的复用与动态计算(@mixin和@function)

目录 一、mixin 1、定义复用的样式代码&#xff0c;接受传参&#xff0c;搭配include使用。 位置传参 关键词传参 ...语法糖接受传入的任意参数 2、在mixin中使用content&#xff0c;获取外部对mixin的追加内容 二、function 三、字符串——值得注意的点 很多时候&#…

[Doris]阿里云搭建Doris,测试环境1FE 1BE

首先&#xff1a;阿里云的国内服务器千万不要用容器搭建&#xff0c;或者自己Dockfile构建镜像。两种方式都不得行&#xff0c;压根拉不到github的镜像&#xff0c;开了镜像加速器也拉不到&#xff0c;不要折腾了&#xff0c;极其愚蠢。 背景&#xff1a;现在测试环境&#xff…

算法力扣刷题记录 五十六【501.二叉搜索树中的众数】

前言 二叉搜索树操作&#xff0c;继续。 记录 五十六【501.二叉搜索树中的众数】 一、题目阅读 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;…

【BUG】已解决:zipfile.BadZipFile: File is not a zip file

已解决&#xff1a;zipfile.BadZipFile: File is not a zip file 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城市开发…

IAR环境下STM32+IAP方案的实现

--基于STM32F103ZET6的UART通讯实现 一、什么是IAP&#xff0c;为什么要IAP IAP即为In Application Programming(在应用中编程)&#xff0c;一般情况下&#xff0c;以STM32F10x系列芯片为主控制器的设备在出厂时就已经使用J-Link仿真器将应用代码烧录了&#xff0c;如果在设备使…

Day16_集合与迭代器

Day16-集合 Day16 集合与迭代器1.1 集合的概念 集合继承图1.2 Collection接口1、添加元素2、删除元素3、查询与获取元素不过当我们实际使用都是使用的他的子类Arraylist&#xff01;&#xff01;&#xff01; 1.3 API演示1、演示添加2、演示删除3、演示查询与获取元素 2 Iterat…

ros笔记03--从零体验ros2话题通信方式

ros笔记03--从零体验ros2话题通信方式 介绍创建步骤体验官方 talker listener 案例基于python开发发布订阅案例 注意事项说明 介绍 主题是 ros2 提供的三种主要接口方式之一&#xff0c;它通常被用于连续的数据流&#xff0c;如传感器数据、机器人状态等。 ros2 是一个强类型的…

Artix7系列FPGA实现SDI视频编解码+UDP以太网传输,基于GTP高速接口,提供工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本博已有的以太网方案本博已有的FPGA图像缩放方案本方案的缩放应用本方案在Xilinx--Kintex系列FPGA上的应用本方案在Xilinx--Zynq系列FPGA上的应用 3、详细设计方案设计原理框图SDI 输入设备Gv8601a 均衡…

SAP Fiori 实战课程(二):新建页面

课程回顾 上一课中,利用Visual studio Code 新建、并运行了一个Demo工程。可以实现对项目的启动,启动后进入一个List清单。 那么本次课程的目前就是在上一节Demo的基础上,从零开始新建一个完整的页面。实现从首页清单,选择行后,鼠标点击,进入下一个页面。 准备工作 在开…

【20】读感 - 架构整洁之道(二)

概述 继上一篇文章讲了前两章的读感&#xff0c;已经归纳总结的重点&#xff0c;这章会继续跟进的看一下&#xff0c;深挖架构整洁之道。 编程范式 编程范式从早期到至今&#xff0c;提过哪些编程范式&#xff0c;结构化编程&#xff0c;面向对象编程&#xff0c;函数式编程…

想要获客如有神助攻,宝藏工具必不可少!

现如今&#xff0c;客户资源的收集和管理成为了一个让很多人都为之烦恼的问题。 然而&#xff0c;随着科技的进步&#xff0c;市场上出现了许多高效的宝藏工具&#xff0c;可以帮助你轻松解决这些问题&#xff0c;让获客如有神助攻&#xff01; 1、丰富的客户来源 无论是附近…

TypeScript体操(二):Utility Type手写实现

目录 前言常用 Utility Types 及其实现Partial<T>Required<T>Readonly<T>Pick<T, K>Omit<T, K>Record<K, T>Exclude<T, U>Extract<T, U>NonNullable<T>ReturnType<T>InstanceType<T>Parameters<T>Con…

synergy配置

今天介绍一个电脑同步软件synergy。 我们开发时一般会用两套设备&#xff0c;如果使用两套键盘操作起来会很麻烦&#xff0c;这个软件就是解决这个问题&#xff0c;可以使用一套键盘同时操作两台电脑&#xff0c;另一台作为客户端被控制。 安装 在两台电脑上各自下载安装syne…

沃文特过会两年仍在注册:营收净利润下滑,三次抽查不合格

《港湾商业观察》施子夫 王璐 在当前IPO严查之际&#xff0c;部分企业的上市进程可谓相当漫长&#xff0c;四川沃文特生物工程股份有限公司&#xff08;以下简称&#xff0c;沃文特&#xff09;就是其中之一。 不过&#xff0c;最近的好消息是&#xff0c;沃文特又更新了招股…

NVIDIA Container Toolkit 安装与配置帮助文档(Ubuntu,Docker)

NVIDIA Container Toolkit 安装与配置帮助文档(Ubuntu,Docker) 本文档详细介绍了在 Ubuntu Server 22.04 上使用 Docker 安装和配置 NVIDIA Container Toolkit 的过程。 概述 NVIDIA 容器工具包使用户能够构建和运行 GPU 加速容器。即可以在容器中使用NVIDIA显卡。 架构图如…

【BUG】已解决:TypeError: Descriptors cannot not be created directly.

已解决&#xff1a;TypeError: Descriptors cannot not be created directly. 目录 已解决&#xff1a;TypeError: Descriptors cannot not be created directly. 【常见模块错误】 【错误原因】 【解决方案】 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来…

谷粒商城实战笔记-46-商品服务-API-三级分类-配置网关路由与路径重写

文章目录 一&#xff0c;准备工作1&#xff0c;新增一级菜单2&#xff0c;新增二级菜单 二&#xff0c;前端树形界面开发1&#xff0c;开发分类展示组件 本节的主要内容&#xff1a; 前端调用三级分类接口&#xff0c;并树形展示 一&#xff0c;准备工作 启动product服务启动…

【开源库学习】libodb库学习(三)

4 查询数据库 如果我们不知道我们正在寻找的对象的标识符&#xff0c;我们可以使用查询在数据库中搜索符合特定条件的对象。ODB查询功能是可选的&#xff0c;我们需要使用--generate-query ODB编译器选项显式请求生成必要的数据库支持代码。 ODB提供了一个灵活的查询API&#x…

RPM、YUM 安装 xtrabackup 8 (mysql 热备系列一)包含rpm安装 mysql 8 配置主从

RPM安装 percona-xtrabackup-80-8.0.35-30.1.el7.x86_64.rpm 官网&#xff1a; https://www.percona.com/ 下载地址&#xff1a; https://www.percona.com/downloads wget https://downloads.percona.com/downloads/percona-distribution-mysql-ps/percona-distribution-mysq…