阅读视图

发现新文章,点击刷新页面。

CSS3动画使用教程

你想要一份更详细、更系统的CSS3动画(animation)使用教程,我会从基础概念到实战案例,一步步拆解CSS3动画的核心用法,让你能轻松上手并灵活运用。

CSS3 动画(animation)全教程

CSS3动画是通过@keyframes定义关键帧,再通过animation属性将动画应用到元素上,能实现比transition更复杂、更灵活的动态效果,且无需JavaScript参与。

一、核心概念理解

在开始写代码前,先理清两个核心部分:

  1. @keyframes(关键帧) :定义动画的"关键状态",比如起始、中间、结束时元素的样式。
  2. animation 属性:将定义好的关键帧动画应用到元素上,并设置动画的时长、循环、速度等规则。

二、基础语法与步骤

步骤1:定义关键帧(@keyframes)
/* 格式:@keyframes 动画名称 { 关键帧规则 } */
@keyframes 动画名称 {
  /* 0% 表示动画开始(也可以用 from 替代) */
  0% {
    /* 起始样式 */
    transform: translateX(0);
    opacity: 0;
  }
  /* 50% 表示动画进行到一半 */
  50% {
    /* 中间样式 */
    transform: translateX(100px);
    opacity: 1;
  }
  /* 100% 表示动画结束(也可以用 to 替代) */
  100% {
    /* 结束样式 */
    transform: translateX(200px);
    opacity: 0;
  }
}
步骤2:应用动画(animation 属性)
/* 给元素添加动画 */
.animated-box {
  width: 100px;
  height: 100px;
  background: #007bff;
  
  /* 核心:animation 复合属性(推荐) */
  /* 格式:动画名称 时长 速度曲线 延迟 循环次数 方向 填充模式 播放状态 */
  animation: 动画名称 2s ease 0.5s infinite alternate forwards running;
  
  /* 也可以拆分为单个属性(便于理解和调试) */
  /* animation-name: 动画名称;          // 必选:指定关键帧名称 */
  /* animation-duration: 2s;            // 必选:动画时长(默认0,无效果) */
  /* animation-timing-function: ease;  // 可选:速度曲线(默认ease) */
  /* animation-delay: 0.5s;             // 可选:延迟播放(默认0) */
  /* animation-iteration-count: infinite; // 可选:循环次数(默认1,infinite无限) */
  /* animation-direction: alternate;    // 可选:播放方向(默认normal) */
  /* animation-fill-mode: forwards;     // 可选:动画结束后样式(默认none) */
  /* animation-play-state: running;     // 可选:播放状态(默认running,paused暂停) */
}

三、关键属性详解(必掌握)

1. 速度曲线(animation-timing-function)

控制动画的播放速度,常用值:

/* 常用值示例 */
.animated-box {
  /* linear:匀速(最常用) */
  animation-timing-function: linear;
  /* ease:慢→快→慢(默认) */
  /* ease-in:慢→快 */
  /* ease-out:快→慢 */
  /* ease-in-out:慢→快→慢(比ease更平缓) */
  /* 自定义贝塞尔曲线(精准控制) */
  /* animation-timing-function: cubic-bezier(0.1, 0.7, 1.0, 0.1); */
}
2. 播放方向(animation-direction)

控制动画是否反向播放:

.animated-box {
  /* normal:正常播放(默认),从0%→100% */
  /* alternate:交替播放,奇数次正向(0%→100%),偶数次反向(100%→0%) */
  /* reverse:反向播放(100%→0%) */
  /* alternate-reverse:反向交替播放 */
  animation-direction: alternate;
}
3. 填充模式(animation-fill-mode)

控制动画开始前/结束后的元素样式:

.animated-box {
  /* none:默认,动画结束后回到初始样式 */
  /* forwards:动画结束后,保持最后一帧样式 */
  /* backwards:动画延迟期间,保持第一帧样式 */
  /* both:同时应用forwards和backwards */
  animation-fill-mode: forwards;
}
4. 播放状态(animation-play-state)

常用于通过:hover、JS控制动画暂停/播放:

.animated-box {
  animation: move 2s infinite;
}
/* 鼠标悬停时暂停动画 */
.animated-box:hover {
  animation-play-state: paused;
}

四、实战案例(直接复用)

案例1:呼吸灯效果(透明度变化)
/* 定义关键帧 */
@keyframes breathe {
  0% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.5;
    transform: scale(1.1);
  }
  100% {
    opacity: 1;
    transform: scale(1);
  }
}

/* 应用动画 */
.breathe-box {
  width: 80px;
  height: 80px;
  background: #ff6700;
  border-radius: 50%;
  /* 匀速、无限循环 */
  animation: breathe 2s linear infinite;
}
案例2:加载动画(旋转+多元素)
<!-- HTML结构 -->
<div class="loader">
  <div class="loader-item"></div>
  <div class="loader-item"></div>
  <div class="loader-item"></div>
</div>
/* 定义旋转关键帧 */
@keyframes load {
  0% {
    transform: translateY(0);
    opacity: 0.8;
  }
  50% {
    transform: translateY(-20px);
    opacity: 0.2;
  }
  100% {
    transform: translateY(0);
    opacity: 0.8;
  }
}

.loader {
  display: flex;
  gap: 8px;
  justify-content: center;
  align-items: center;
  height: 100px;
}

.loader-item {
  width: 12px;
  height: 30px;
  background: #007bff;
  border-radius: 6px;
  animation: load 1.2s ease infinite;
}
/* 给每个小球设置不同延迟,实现错落效果 */
.loader-item:nth-child(2) {
  animation-delay: 0.2s;
}
.loader-item:nth-child(3) {
  animation-delay: 0.4s;
}
案例3:文字渐入动画
@keyframes text-fade {
  0% {
    transform: translateY(20px);
    opacity: 0;
  }
  100% {
    transform: translateY(0);
    opacity: 1;
  }
}

.fade-text {
  font-size: 24px;
  animation: text-fade 0.8s ease forwards;
  /* 初始状态隐藏 */
  opacity: 0;
}

五、使用注意事项

  1. 性能优化:优先使用transformopacity属性做动画(浏览器硬件加速,无重绘),避免用widthheighttopleft(会触发频繁重排,卡顿)。
  2. 兼容性:现代浏览器(Chrome/Firefox/Safari/Edge)均支持CSS3动画,无需加前缀;如需兼容老旧浏览器(如IE10-),可加前缀-webkit-(如@-webkit-keyframes-webkit-animation)。
  3. 动画暂停:通过animation-play-state: paused暂停动画,比重新设置时长为0更优雅。

总结

  1. 核心结构:CSS3动画由@keyframes(定义关键帧)和animation(应用动画)两部分组成,animation-duration是必选属性(否则无动画效果)。
  2. 常用属性animation-iteration-count: infinite(无限循环)、animation-direction: alternate(交替播放)、animation-fill-mode: forwards(保持结束样式)是高频组合。
  3. 性能原则:动画优先操作transformopacity,避免触发页面重排,保证动画流畅。

你可以把这些案例代码复制到HTML文件中运行,修改关键帧的样式、动画时长、速度曲线等参数,直观感受不同设置的效果,很快就能熟练掌握。如果想实现某个特定的动画效果(比如弹跳、滑动、闪烁),可以告诉我,我会针对性给出代码。

React、TypeScript、reduce 以及 Ant Design Pro Components(antProcomponent)搭建开发环境教程

你想要的是一套完整的教程,指导如何搭建一个结合了 React、TypeScript、reduce 以及 Ant Design Pro Components(antProcomponent)的开发环境,我会一步步带你完成这个过程。

一、环境准备(前置条件)

在开始前,请确保你的电脑已安装以下工具:

  1. Node.js(推荐 16.x 或 18.x 版本,可通过 node -v 检查)
  2. npm 或 yarn(npm 随 Node.js 自带,yarn 可通过 npm install -g yarn 安装)
  3. 代码编辑器(推荐 VS Code)

二、搭建 React + TypeScript 基础项目

Ant Design Pro 提供了开箱即用的脚手架,能快速集成 TypeScript 和 Pro Components,比手动配置更高效:

步骤 1:创建 Ant Design Pro 项目

打开终端,执行以下命令(选择 TypeScript 模板):

# 使用官方脚手架创建项目
npm create umi@latest my-pro-app
# 或用 yarn
yarn create umi my-pro-app

执行后会出现交互式选择,按以下选项配置:

  1. 选择 ant-design-pro(Pro 模板)
  2. 选择 TypeScript(语言)
  3. 选择 simple(简易模板,适合新手)
  4. 确认安装依赖(等待依赖下载完成)
步骤 2:安装依赖并启动项目

进入项目目录,安装依赖并启动:

cd my-pro-app
# 安装依赖
npm install
# 启动开发服务
npm run start

启动成功后,浏览器会自动打开 http://localhost:8000,能看到 Ant Design Pro 的基础页面,说明 React + TypeScript + Pro Components 环境已搭建完成。

三、集成 reduce(数组方法)的实战示例

React 中常使用 reduce 处理数组数据(比如数据聚合、筛选、格式化),结合 TypeScript 能保证类型安全,以下是结合 Pro Components(如 ProTable)的实战示例:

示例:用 reduce 处理表格数据并渲染 ProTable
  1. src/pages 下新建 ReduceDemo.tsx 文件,写入以下代码:
import React from 'react';
import { ProTable } from '@ant-design/pro-components';

// 定义数据类型(TypeScript 类型约束)
interface UserData {
  id: number;
  name: string;
  department: string;
  salary: number;
}

const ReduceDemo: React.FC = () => {
  // 原始模拟数据
  const rawData: UserData[] = [
    { id: 1, name: '张三', department: '前端', salary: 15000 },
    { id: 2, name: '李四', department: '后端', salary: 18000 },
    { id: 3, name: '王五', department: '前端', salary: 16000 },
    { id: 4, name: '赵六', department: '后端', salary: 20000 },
  ];

  // 用 reduce 聚合:按部门分组,计算每个部门的平均工资
  const departmentSalary = rawData.reduce((acc, item) => {
    // 类型守卫,确保 acc 结构正确
    if (!acc[item.department]) {
      acc[item.department] = {
        total: 0,
        count: 0,
        average: 0,
        list: [] as UserData[],
      };
    }
    // 累加工资和人数
    acc[item.department].total += item.salary;
    acc[item.department].count += 1;
    // 存入当前用户
    acc[item.department].list.push(item);
    // 计算平均工资(保留2位小数)
    acc[item.department].average = Number(
      (acc[item.department].total / acc[item.department].count).toFixed(2)
    );
    return acc;
  }, {} as Record<string, { total: number; count: number; average: number; list: UserData[] }>);

  // 转换为 ProTable 可渲染的格式
  const tableData = Object.entries(departmentSalary).map(([dept, data]) => ({
    department: dept,
    totalSalary: data.total,
    personCount: data.count,
    averageSalary: data.average,
  }));

  // ProTable 列配置
  const columns = [
    {
      title: '部门',
      dataIndex: 'department',
      key: 'department',
    },
    {
      title: '总工资',
      dataIndex: 'totalSalary',
      key: 'totalSalary',
    },
    {
      title: '人数',
      dataIndex: 'personCount',
      key: 'personCount',
    },
    {
      title: '平均工资',
      dataIndex: 'averageSalary',
      key: 'averageSalary',
    },
  ];

  return (
    <div style={{ padding: 20 }}>
      <h2>Reduce + ProTable 实战示例</h2>
      <ProTable
        dataSource={tableData}
        columns={columns}
        rowKey="department"
        pagination={false}
        title={() => '各部门工资统计(基于reduce聚合)'}
      />
    </div>
  );
};

export default ReduceDemo;
  1. 配置路由:修改 src/config/routes.ts,添加新路由:
import { IRouteProps } from '@umijs/max';

const routes: IRouteProps[] = [
  {
    path: '/',
    redirect: '/reduce-demo',
  },
  {
    path: '/reduce-demo',
    name: 'Reduce示例',
    component: './ReduceDemo',
  },
];

export default routes;
  1. 重启项目(npm run start),访问 http://localhost:8000/reduce-demo,就能看到用 reduce 聚合后的数据通过 ProTable 渲染的表格。

四、关键知识点解释

  1. TypeScript 类型约束
  • 定义 UserData 接口规范原始数据结构,避免类型错误;
  • Record<string, ...> 约束 reduce 累加器的类型,确保 acc 的属性和值类型符合预期。
  1. reduce 核心逻辑
  • 第一个参数:回调函数,接收 acc(累加器)和 item(当前项),返回更新后的累加器;
  • 第二个参数:累加器初始值(这里是空对象,且用 TypeScript 定义了结构);
  • 作用:替代循环,高效完成“分组 + 计算”的聚合操作。
  1. Ant Design Pro Components 优势
  • ProTable 内置了分页、筛选、排序等功能,比原生 Table 更易用;
  • 支持 TypeScript 类型推导,列配置的 dataIndex 会自动校验是否匹配数据源。

总结

  1. 环境搭建核心:通过 Ant Design Pro 脚手架快速集成 React + TypeScript + Pro Components,无需手动配置复杂的 Webpack/TSConfig;
  2. reduce 实战:结合 TypeScript 类型约束,用 reduce 完成数组聚合(分组、计算),再通过 ProTable 渲染结果;
  3. 关键要点:TypeScript 接口/类型守卫保证类型安全,reduce 替代循环提升代码简洁性,Pro Components 简化业务组件开发。

如果需要扩展功能(比如接口请求、状态管理),可以基于这个基础环境,结合 Umi Max 的请求库(@umijs/max)或 React Context/Redux 进一步开发。

❌