一、CSS 动画基础:Transition 和 Transform
1. transition
属性详解
transition: [property] [duration] [timing-function] [delay];
属性详解:
属性名 | 说明 | 示例 |
---|---|---|
transition-property | 要过渡的属性名(可多个) | transition-property: transform, opacity; |
transition-duration | 动画持续时间(单位:s/ms) | transition-duration: 0.3s; |
transition-timing-function | 动画节奏函数(缓动曲线) | transition-timing-function: ease-in-out; |
transition-delay | 延迟时间 | transition-delay: 0.1s; |
常用的 timing-function 取值:
值 | 效果 |
---|---|
ease | 默认,慢-快-慢 |
linear | 匀速 |
ease-in | 加速进入 |
ease-out | 减速退出 |
ease-in-out | 先加速后减速 |
cubic-bezier(x1, y1, x2, y2) | 自定义贝塞尔曲线 |
示例:
.box { transition: transform 0.3s ease-in-out 0s; }
2. transform
属性详解
transform: function(value);
常见的变换函数及示例:
函数名 | 功能 | 示例 |
---|---|---|
translate(x, y) | 平移(支持 px , % ) | translate(10px, 20px) |
translateX(x) / translateY(y) | 水平/垂直移动 | translateX(100%) |
scale(x, y) | 缩放(默认中心点) | scale(1.2, 1.2) |
scaleX(x) / scaleY(y) | 单轴缩放 | scaleY(0.8) |
rotate(angle) | 旋转,单位 deg 、rad | rotate(45deg) |
skew(x-angle, y-angle) | 倾斜 | skew(10deg, 5deg) |
matrix(a, b, c, d, e, f) | 矩阵变换(高级) | matrix(1, 0, 0, 1, 0, 0) |
.box:hover { transform: scale(1.1) rotate(10deg) translateX(5px); }
animation
:
它实际上是下面这些属性的缩写形式:
animation:
animation-name
animation-duration
animation-timing-function
animation-delay
animation-iteration-count
animation-direction
animation-fill-mode
animation-play-state;
你可以只写一部分,浏览器会使用默认值。
🔧 各子属性解释
子属性 | 作用 | 示例 |
---|---|---|
animation-name | 指定要使用的关键帧名称 | fadeIn |
animation-duration | 动画持续时间 | 2s 或 500ms |
animation-timing-function | 动画节奏 | ease 、linear 、ease-in-out 、cubic-bezier(...) |
animation-delay | 动画延迟开始的时间 | 1s |
animation-iteration-count | 播放次数 | infinite 、1 、2 |
animation-direction | 动画方向 | normal 、reverse 、alternate |
animation-fill-mode | 动画结束后元素状态 | forwards 、backwards 、both 、none |
animation-play-state | 控制动画播放或暂停 | running 、paused |
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.box {
animation: fadeIn 2s ease-in-out forwards;
}
上面这段代码的意思是:元素 .box
在加载后会用 fadeIn
关键帧在 2 秒内从透明变为不透明,采用 ease-in-out
的节奏,并在动画结束后保持最后的状态(forwards
)。
是不是觉得animation和transition很像,但是其实他们是有不同的应用场景的
场景 | 推荐方案 | 原因 |
---|---|---|
简单状态变化(如悬停、点击) | transition | 代码简洁,性能开销小 |
复杂动画序列(如弹跳、旋转) | animation | 无需依赖外部状态,可独立控制 |
需要暂停 / 恢复动画 | animation + JS | 通过 animation-play-state: paused/running 控制 |
仅需触发一次的动画 | transition | 无需定义 @keyframes ,更轻量 |
总结
- 选
transition
:如果动画是由用户交互(如点击、悬停)触发,且只需从 A 状态到 B 状态的简单过渡。 - 选
animation
:如果动画需要自动播放、循环执行,或需要多阶段复杂控制(如弹跳、摇摆)。
二、Vue 动画详解
1. <transition>
组件的工作机制
Vue 会自动为进入和离开的元素添加 CSS 类名。
类名规范(假设 name="fade"
):
类名 | 生命周期 | 说明 |
---|---|---|
.fade-enter-from | 进入前 | 初始状态(例如 opacity: 0) |
.fade-enter-active | 进入期间 | 设置过渡属性(如 transition) |
.fade-enter-to | 进入后 | 目标状态(例如 opacity: 1) |
.fade-leave-from | 离开前 | 当前状态(例如 opacity: 1) |
.fade-leave-active | 离开期间 | 设置离开的过渡属性 |
.fade-leave-to | 离开后 | 目标状态(例如 opacity: 0) |
<template>
<button @click="show = !show">Toggle</button>
<transition name="fade">
<div v-if="show" class="box">Hello Vue!</div>
</transition>
</template>
<style>
.fade-enter-from, .fade-leave-to {
opacity: 0;
transform: translateY(20px);
}
.fade-enter-to, .fade-leave-from {
opacity: 1;
transform: translateY(0);
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.4s ease, transform 0.4s ease;
}
</style>
2. <transition>
的配置属性
属性 | 类型 | 说明 |
---|---|---|
name | String | 自动生成类名前缀 |
appear | Boolean | 初次渲染是否应用动画 |
mode | String | 动画切换顺序,out-in 或 in-out |
type | String | animation 或 transition (可选) |
duration | Number/Object | 自定义动画时长,防止“闪现” |
例子
<transition name="fade" mode="out-in" appear :duration="500">
<div v-if="visible">展示内容</div>
</transition>
3. JavaScript 钩子函数
如果你不想依赖 CSS,可以完全使用 JavaScript 控制:
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@leave="leave"
>
<div v-if="show">动画内容</div>
</transition>
<script>
export default {
methods: {
beforeEnter(el) {
el.style.opacity = 0;
},
enter(el, done) {
setTimeout(() => {
el.style.transition = 'opacity 0.5s';
el.style.opacity = 1;
done(); // 动画完成时必须调用
}, 0);
},
afterEnter(el) {
console.log('进入动画完成');
},
leave(el, done) {
el.style.transition = 'opacity 0.5s';
el.style.opacity = 0;
setTimeout(done, 500); // 动画持续时间匹配
}
}
};
</script>
4. 列表动画 <transition-group>
<transition-group name="list" tag="ul">
<li v-for="item in items" :key="item.id">{{ item.text }}</li>
</transition-group>
<style>
.list-enter-from, .list-leave-to {
opacity: 0;
transform: translateY(20px);
}
.list-enter-active, .list-leave-active {
transition: all 0.3s ease;
}
</style>