3、CSS动画实战:使用@keyframes定义动画、v-enter-active/v-leave-active配合animation、动画持续时间与延迟控制、结合第三方动画库(Animate.css)
好,咱们直接进入正题。CSS动画这块,说实话是Vue动画系统里最灵活、也最容易被低估的部分。很多人一上来就想着用JS库,其实纯CSS能解决大部分场景。我这些年做过的项目里,大概有70%的过渡动画都是用CSS搞定的。
3.1 @keyframes:动画的灵魂
先说说@keyframes。这东西说白了就是定义动画的「关键帧」。你告诉浏览器:从哪开始、到哪结束、中间经过哪些状态。剩下的中间过程,浏览器帮你算。
@keyframes slideIn {
0% {
transform: translateX(-100%);
opacity: 0;
}
60% {
transform: translateX(10%);
opacity: 0.8;
}
100% {
transform: translateX(0);
opacity: 1;
}
}
我个人习惯用百分比来定义关键帧,而不是from/to。为什么?因为百分比更灵活,你可以在中间插入更多状态。比如上面这个例子,我加了个60%的中间态,让元素先弹出去一点再回来,看起来更自然。
3.2 把@keyframes挂到Vue的过渡钩子上
现在问题来了:怎么把@keyframes和Vue的v-enter-active/v-leave-active结合起来?
其实很简单。你想想看,v-enter-active就是元素「入场」期间要执行的样式,v-leave-active就是「离场」期间。我们直接把animation属性写进去就行。
.my-enter-active {
animation: slideIn 0.6s ease-out;
}
.my-leave-active {
animation: slideOut 0.4s ease-in;
}
@keyframes slideOut {
0% {
transform: translateX(0);
opacity: 1;
}
100% {
transform: translateX(100%);
opacity: 0;
}
}
然后在模板里这样用:
<transition name="my">
<div v-if="show" class="box">我是动画元素</div>
</transition>
嗯,这里要注意:Vue会自动把name属性的值拼到类名上。比如name="my",那入场动画的类就是my-enter-active,离场就是my-leave-active。
animation写到了v-enter和v-leave上,结果动画根本不执行。后来才发现,v-enter只是定义初始状态,真正执行动画的是v-enter-active。别搞混了。
3.3 动画持续时间与延迟控制
控制动画时长和延迟,说白了就是调两个参数:animation-duration和animation-delay。
但这里有个坑——入场和离场的时长往往不一样。我个人习惯入场慢一点(0.5s-0.8s),离场快一点(0.2s-0.4s)。为什么?因为用户需要看清新元素怎么进来的,但旧元素离开时越快越好,别让人等着。
.fade-enter-active {
animation: fadeIn 0.6s ease-out;
}
.fade-leave-active {
animation: fadeOut 0.3s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
@keyframes fadeOut {
from { opacity: 1; transform: translateY(0); }
to { opacity: 0; transform: translateY(-20px); }
}
延迟控制呢?animation-delay可以让你等一会儿再开始动画。这个在列表动画里特别有用——每个元素依次延迟一点点,形成「波浪效果」。
3.4 结合第三方动画库:Animate.css
说实话,自己写@keyframes虽然灵活,但有时候太慢了。尤其是项目赶工期的时候,哪有时间调那些缓动曲线?这时候就该请出Animate.css了。
Animate.css是个啥?说白了就是一个现成的动画库,里面预置了上百种动画效果。淡入淡出、弹跳、翻转、旋转...应有尽有。你只需要加个类名就行。
安装方式很简单:
npm install animate.css
然后在main.js里引入:
import 'animate.css'
接下来怎么和Vue的transition结合?我直接给你看代码:
<transition
enter-active-class="animate__animated animate__bounceIn"
leave-active-class="animate__animated animate__bounceOut"
>
<div v-if="show" class="box">看我弹进来弹出去</div>
</transition>
看到了吗?enter-active-class和leave-active-class这两个属性,直接替换了原来的v-enter-active类名。你只需要把Animate.css的类名填进去就行。
animate__animated前缀,这是他们v4版本的规定。我刚开始用的时候忘了加,折腾了半天才发现。
如果你想自定义动画时长,可以这样:
<transition
enter-active-class="animate__animated animate__bounceIn"
leave-active-class="animate__animated animate__bounceOut"
:duration="600"
>
<div v-if="show" class="box">时长统一为600ms</div>
</transition>
或者入场和离场分别控制:
<transition
enter-active-class="animate__animated animate__bounceIn"
leave-active-class="animate__animated animate__bounceOut"
:duration="{ enter: 800, leave: 400 }"
>
<div v-if="show" class="box">入场800ms,离场400ms</div>
</transition>
3.5 实战中的选择建议
说了这么多,到底什么时候自己写@keyframes,什么时候用Animate.css?我个人的经验是这样的:
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 简单的淡入淡出、滑动 | 自己写@keyframes | 代码量少,性能好,不需要额外依赖 |
| 复杂的弹跳、翻转、旋转 | Animate.css | 现成的效果,省时省力 |
| 需要精细控制每个关键帧 | 自己写@keyframes | Animate.css无法满足定制需求 |
| 项目赶工期、原型验证 | Animate.css | 快速出效果,后面再优化 |
最后说一句:不管用哪种方式,动画的目的是提升用户体验,不是炫技。我见过有人把页面做成「动画大杂烩」,每个元素都在跳,结果用户根本找不到重点。记住,克制才是最高级的审美。