在React中实现好看的动画Framer Motion(案例:跨DOM元素平滑过渡)

前言

介绍

Framer Motion 是一个适用于 React 网页开发的动画库,它可以让开发者轻松地在他们的项目中添加复杂和高性能的动画效果。该库提供了一整套针对 React 组件的动画、过渡和手势处理功能,使得通过声明式的 API 来创建动画变得简单直观。

接下来我将带你使用 Framer Motion 实现一个选中样式平滑过渡的案例。

案例

2023-12-16_10-15-30.gif

基本环境

本案例基于 Vite + React + TypeScript + TailwindCSS 搭建。TailwindCSS 不是必须的,我主要是为了不写 CSS 样式,若想实现和本案例相同的效果,可以安装一下 TailwindCSS。

基本页面

基本页面比较简单,主要就是渲染不同的导航链接,当点击时设置选中的导航,在选中的导航内渲染一个 span 用于显示选中样式,App.tsx

import { useState } from "react";

const navs = [
  {
    name: "Home",
    href: "#home",
  },
  {
    name: "About",
    href: "#about",
  },
  {
    name: "Contact",
    href: "#contact",
  },
];

function App() {
  const [activeNav, setActiveNav] = useState("#home");

  return (
    <div className="mx-auto grid h-full max-w-2xl place-items-center space-y-4 py-4">
      <div className="space-y-8">
        <ul className="flex gap-2">
          {navs.map((nav, index) => (
            <li key={index} className="relative">
              <a
                href={nav.href}
                className="block rounded-md px-4 py-2 text-sm font-medium"
                onClick={() => {
                  setActiveNav(nav.href);
                }}
              >
                {nav.name}

                {nav.href === activeNav && (
                  <span className="absolute inset-0 -z-10 rounded-full bg-gray-100"></span>
                )}
              </a>
            </li>
          ))}
        </ul>

        <ul className="flex flex-col gap-2">
          {navs.map((nav, index) => (
            <li key={index} className="relative">
              <a
                href={nav.href}
                className="block rounded-md px-4 py-1 text-sm font-medium hover:bg-gray-100"
                onClick={() => {
                  setActiveNav(nav.href);
                }}
              >
                {nav.name}

                {nav.href === activeNav && (
                  <span className="absolute inset-y-0 left-0 w-1 rounded-full bg-gray-200"></span>
                )}
              </a>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}

export default App;
  1. navs 数组:定义了导航链接的数据。
  2. activeNav 状态:存储当前选中的导航项。
  3. 导航列表:通过<ul>元素创建垂直和水平的导航条目。
  4. 点击事件处理:更新activeNav状态以高亮显示当前选中导航。
  5. 条件渲染:根据activeNav状态在选中的导航下显示指示标识。

此时已经完成了案例的基本样式,通过点击发现此时还没有任何动画,选中之间的过渡比较生硬。

npm 安装 Framer Motion:

npm install framer-motion

使用 pnpm:

pnpm add framer-motion

修改 app.tsx

import { motion } from "framer-motion";

<motion.span
	className="absolute inset-0 -z-10 rounded-full bg-gray-100"
	layoutId="activeNav"
	transition={{
		type: "spring",
		stiffness: 380,
		damping: 30,
	}}
></motion.span>

<motion.span
	className="absolute inset-y-0 left-0 w-1 rounded-full bg-gray-200"
	layoutId="activeNav2"
	transition={{
		type: "spring",
		stiffness: 380,
		damping: 30,
	}}
></motion.span>

引入 framer-motion,然后把设置选中样式的 span 改为 motion.span,添加 layoutIdtransition 属性,动画设置为 spring 弹簧动画。

layoutId 用来创建动画以平滑地过渡共享元素的布局变化。
transition 属性用来定义动画的持续时间、延迟、缓动函数(如线性、弹性)、循环次数等特性。
stiffness 这个参数影响弹簧的硬度。一个更高的刚度值意味着弹簧更硬,它会更快地回到它的起始位置,导致动画更快地开始并且拥有一个更小的震荡周期。简言之,刚度越大,弹簧越“紧”,动画运动越快。
damping 这个参数影响弹簧动画的阻尼效果,也就是减震效果。一个更高的阻尼值会导致弹簧运动时震荡得更少,从而更快地稳定下来。如果阻尼值设置得很低,动画会在达到静止状态之前在结束位置附近做较多的震荡。

完整代码

import { useState } from "react";

import { motion } from "framer-motion";

const navs = [
  {
    name: "Home",
    href: "#home",
  },
  {
    name: "About",
    href: "#about",
  },
  {
    name: "Contact",
    href: "#contact",
  },
];

function App() {
  const [activeNav, setActiveNav] = useState("#home");

  return (
    <div className="mx-auto grid h-full max-w-2xl place-items-center space-y-4 py-4">
      <div className="space-y-8">
        <ul className="flex gap-2">
          {navs.map((nav, index) => (
            <li key={index} className="relative">
              <a
                href={nav.href}
                className="block rounded-md px-4 py-2 text-sm font-medium"
                onClick={() => {
                  setActiveNav(nav.href);
                }}
              >
                {nav.name}

                {nav.href === activeNav && (
                  <motion.span
                    className="absolute inset-0 -z-10 rounded-full bg-gray-100"
                    layoutId="activeNav"
                    transition={{
                      type: "spring",
                      stiffness: 380,
                      damping: 30,
                    }}
                  ></motion.span>
                )}
              </a>
            </li>
          ))}
        </ul>

        <ul className="flex flex-col gap-2">
          {navs.map((nav, index) => (
            <li key={index} className="relative">
              <a
                href={nav.href}
                className="block rounded-md px-4 py-1 text-sm font-medium hover:bg-gray-100"
                onClick={() => {
                  setActiveNav(nav.href);
                }}
              >
                {nav.name}

                {nav.href === activeNav && (
                  <motion.span
                    className="absolute inset-y-0 left-0 w-1 rounded-full bg-gray-200"
                    layoutId="activeNav2"
                    transition={{
                      type: "spring",
                      stiffness: 380,
                      damping: 30,
                    }}
                  ></motion.span>
                )}
              </a>
            </li>
          ))}
        </ul>
      </div>
    </div>
  );
}

export default App;

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

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

相关文章

ChatGPT4 Excel 高级组合函数用法index+match完成实际需求

在Excel 函数用法中有一对组合函数使用是非常多的,那就是Index+match组合函数。 接下来我们用一个实际的需求让ChatGPT来帮我们实现一下。 我们给ChatGPT4发送一个prompt:有一个表格A2至A14为业务员B列至H列为1月至7月的销售额,请根据J2单元格的业务员与K2单元格的月份查找出…

DevOps搭建(二)-阿里云镜像仓库的使用详解

博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码下载地址&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb;…

使用令牌桶和漏桶实现请求限流逻辑

实现请求限流 令牌桶算法原理实现案例案例目的:实例demo运行结果: 漏桶算法原理:实现案例:案例目的:案例代码运行结果: 令牌桶算法和漏桶算法是两种常用的限流算法&#xff0c;用于控制系统对请求或数据的访问速率。下面分别详细解释这两种算法的原理. 令牌桶算法 原理 令牌桶…

前端传递参数,后端如何接收

目录 简单参数 传递方式 获取方式一 获取方式二 相关注解 实体参数 数组集合参数 传递方式 相关注解 获取方式一 获取方式二 日期参数 传递方式 相关注解 获取方式 json参数 传递方式 相关注解 获取方式 路径参数 传递方式 相关注解 获取方式 传递多个…

DHCP最全讲解!(原理+配置)

一、概述 随着网络规模的不断扩大&#xff0c;网络复杂度不断提升&#xff0c;网络中的终端设备例如主机、手机、平板等&#xff0c;位置经常变化。终端设备访问网络时需要配置IP地址、网关地址、DNS服务器地址等。采用手工方式为终端配置这些参数非常低效且不够灵活。IETF于19…

day04-报表技术PDF

1 EasyPOI导出word 需求&#xff1a;使用easyPOI方式导出合同word文档 Word模板和Excel模板用法基本一致&#xff0c;支持的标签也是一致的&#xff0c;仅仅支持07版本的word也是只能生成后缀是docx的文档&#xff0c;poi对doc支持不好所以easyPOI中就没有支持doc&#xff0c…

【Linux】内核结构

一、Linux内核结构介绍 Linux内核结构框图 二、图解Linux系统架构 三、驱动认知 1、为什么要学习写驱动2、文件名与设备号3、open函数打通上层到底层硬件的详细过程 四、Shell Shell脚本 一、Linux内核结构介绍 Linux 内核是操作系统的核心部分&#xff0c;它负责管理系…

数据结构 之map/set练习

文章目录 1. 只出现一次的数字算法原理&#xff1a;代码&#xff1a; 2. 随机链表的复制算法原理&#xff1a;代码&#xff1a; 3. 宝石与石头算法原理&#xff1a;代码&#xff1a; 4. 坏键盘打字算法原理&#xff1a;代码&#xff1a; 5. 前K个高频单词算法原理&#xff1a;代…

UGUI 鼠标悬浮UI出现弹框,鼠标在图片边缘出现闪烁

1、背景&#xff1a;鼠标悬浮在UI上出现提示框 public class SpecialParam_list : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler {public void OnPointerEnter(PointerEventData eventData){TipBox.Instance.ShowBox(Input.mousePosition, value);}public void …

【从零开始学习--设计模式--代理模式】

返回首页 前言 感谢各位同学的关注与支持&#xff0c;我会一直更新此专题&#xff0c;竭尽所能整理出更为详细的内容分享给大家&#xff0c;但碍于时间及精力有限&#xff0c;代码分享较少&#xff0c;后续会把所有代码示例整理到github&#xff0c;敬请期待。 此章节介绍建…

基于中小微企业_个体工商户的信贷评分卡模型和用户画像(论文_专利_银行调研建模使用)

背景介绍 信用贷款是指由银行或其他金融机构向中小微企业和个体工商户提供的一种贷款产品。该贷款的特点是无需提供抵押品或担保&#xff0c;主要依据借款人的信用状况来进行评估和审批。 中小微企业和个体工商户信用贷款的申请流程相对简单&#xff0c;申请人只需要提供个人…

飞天使-docker知识点6-容器dockerfile各项名词解释

文章目录 docker的小技巧dockerfile容器为什么会出现启动了不暂停查看docker 网桥相关信息 docker 数据卷 docker的小技巧 [rootlight-test playbook-vars[]# docker inspect -f "{{.NetworkSettings.IPAddress}}" d3a9ae03ae5f 172.17.0.4docker d3a9ae03ae5f:/etc…

测试用例设计方法之判定表详解!!

理论部分 判定表是分析和表达多种输入条件下系统执行不同动作的工具&#xff0c;它可以把复杂的逻辑关系和多种 条件组合的情况表达得既具体又明确。 条件桩(Condition Stub)动作桩(Action Stub&#xff09;条件项(Condition Entry&#xff09;动作项(Action Entry&#xff0…

python+requests+pytest 接口自动化实现

最近工作之余拿公司的项目写了一个接口测试框架&#xff0c;功能还不是很完善&#xff0c;算是抛砖引玉了&#xff0c;欢迎各位来吐槽。 主要思路&#xff1a; ①对 requests 进行二次封装&#xff0c;做到定制化效果 ②使用 excel 存放接口请求数据&#xff0c;作为数据驱动 ③…

配电房环境监测模块

配电房环境监测模块是一个智能系统&#xff0c;依托电易云-智慧电力物联网平台&#xff0c;旨在实时监控配电房内部的环境参数&#xff0c;以确保配电设备的正常运行。该模块包括以下功能&#xff1a; 温度监测&#xff1a;对配电房内的温度进行实时监测&#xff0c;防止因温度…

CSS 基础

文章目录 CSS 常见的属性CSS 常见样式行内样式内嵌样式导入样式 CSS 选择器标签选择器id选择器类选择器全局选择器属性选择器组合选择器 CSS 常见应用表格列表导航栏下拉菜单提示工具图片廊 CSS (Cascading Style Sheets&#xff0c;层叠样式表&#xff09;&#xff0c;是一种用…

Pytorch当中的.detach()操作是什么意思

.detach() 是 PyTorch 中用于从计算图中分离张量的方法。当我们在PyTorch中进行张量运算时&#xff0c;操作会构建一个计算图来跟踪计算历史&#xff0c;这个计算图用于自动求导和反向传播来计算梯度。 使用.detach()方法可以将一个张量从当前的计算图中分离出来&#xff0c;使…

【C语言】动态内存管理(C语言的难点与精华,数据结构的前置知识,你真的掌握了吗?)

文章目录 引言一、为什么要动态内存分配二、动态内存分配的相关函数2.1 malloc2.2 free2.3 calloc2.4 realloc 三、常见的动态内存的错误3.1 对NULL指针的解引用3.2 对动态内存越界访问3.3 对非动态内存释放3.4 对动态内存部分释放3.5 对动态内存多次释放3.6 未对动态内存释放&…

Unity中Shader URP的安装与设置

文章目录 前言一、URP安装1、Window -> Project Manager -> 搜索 Render 二、URP设置1、创建一个URP配置文件2、渲染管线的修改&#xff08;当为空时&#xff0c;使用的是 BuildIn Render Pipeline&#xff09;3、这时我们新建一个对象。使用的材质球默认使用 URP 默认Sh…

【JAVA面向对象练习】---第四天

数据求和类 定义一个类Demo,其中定义一个求两个数据和的方法&#xff0c;定义一个测试了Test&#xff0c;进行测试。 package com.fuhai.day04;public class Sum {private double a;private double b;public double getA() {return a;}public void setA(double a) {this.a a…
最新文章