动画

使用@keyframes创建复杂动画

什么是CSS动画?

CSS动画允许您创建复杂的动画效果,而无需使用JavaScript。通过@keyframes规则,您可以定义动画序列中的各个阶段。CSS动画比过渡更强大,可以创建多阶段、循环和复杂的动画序列。

动画 vs 过渡:
  • 过渡:需要触发条件,简单属性变化
  • 动画:自动播放或通过类触发,复杂关键帧序列
  • 动画支持循环、反向、暂停等高级功能
  • 动画更适合创建复杂的连续效果

CSS动画示例 - 脉冲效果

@keyframes规则

@keyframes规则用于定义动画序列,可以指定动画在不同时间点的样式:

CSS
@keyframes animationName {
    0% {
        /* 起始状态 */
        opacity: 0;
        transform: translateX(-100px);
    }
    50% {
        /* 中间状态 */
        opacity: 1;
        transform: translateX(0);
    }
    100% {
        /* 结束状态 */
        opacity: 0;
        transform: translateX(100px);
    }
}

使用from和to

对于简单的两阶段动画,可以使用from和to关键字:

CSS
@keyframes fadeIn {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

多阶段动画

可以定义任意数量的关键帧:

CSS
@keyframes complexAnimation {
    0% { transform: translateY(0) rotate(0deg); }
    25% { transform: translateY(-50px) rotate(90deg); }
    50% { transform: translateY(0) rotate(180deg); }
    75% { transform: translateY(50px) rotate(270deg); }
    100% { transform: translateY(0) rotate(360deg); }
}

动画属性

CSS动画涉及多个属性来控制动画的行为:

属性 描述 示例 默认值
animation-name 指定@keyframes动画的名称 fadeIn, slideIn none
animation-duration 指定动画完成一个周期所需时间 1s, 500ms 0s
animation-timing-function 指定动画的速度曲线 ease, linear, ease-in-out ease
animation-delay 指定动画开始前的延迟时间 0s, 1s 0s
animation-iteration-count 指定动画播放次数 1, 3, infinite 1
animation-direction 指定动画播放方向 normal, reverse, alternate normal
animation-fill-mode 指定动画执行前后如何应用样式 none, forwards, backwards none
animation-play-state 指定动画播放状态 running, paused running

animation-fill-mode详解

控制动画执行前后元素的样式:

CSS
/* 默认值,动画前后不应用任何样式 */
.element {
    animation-fill-mode: none;
}

/* 动画完成后保持最后一帧的样式 */
.element {
    animation-fill-mode: forwards;
}

/* 动画开始前应用第一帧的样式 */
.element {
    animation-fill-mode: backwards;
}

/* 同时应用forwards和backwards */
.element {
    animation-fill-mode: both;
}

animation-direction详解

控制动画播放方向:

CSS
/* 正常播放 */
.element {
    animation-direction: normal;
}

/* 反向播放 */
.element {
    animation-direction: reverse;
}

/* 先正常再反向,交替播放 */
.element {
    animation-direction: alternate;
}

/* 先反向再正常,交替播放 */
.element {
    animation-direction: alternate-reverse;
}

动画简写属性

可以使用animation简写属性同时设置所有动画属性:

CSS
.element {
    animation: name duration timing-function delay iteration-count direction fill-mode play-state;
}

示例

CSS
.box {
    animation: slideIn 1s ease 0.5s 3 alternate;
}

/* 等同于: */
.box {
    animation-name: slideIn;
    animation-duration: 1s;
    animation-timing-function: ease;
    animation-delay: 0.5s;
    animation-iteration-count: 3;
    animation-direction: alternate;
}

多个动画

可以为元素应用多个动画:

CSS
.element {
    animation: 
        fadeIn 1s ease,
        slideIn 0.5s ease 0.5s;
}

常见动画示例

淡入效果

CSS
@keyframes fadeIn {
    from {
        opacity: 0;
    }
    to {
        opacity: 1;
    }
}

.fade-in {
    animation: fadeIn 1s ease;
}

弹跳效果

CSS
@keyframes bounce {
    0%, 20%, 50%, 80%, 100% {
        transform: translateY(0);
    }
    40% {
        transform: translateY(-30px);
    }
    60% {
        transform: translateY(-15px);
    }
}

.bounce {
    animation: bounce 2s infinite;
}

旋转加载动画

CSS
@keyframes spin {
    0% {
        transform: rotate(0deg);
    }
    100% {
        transform: rotate(360deg);
    }
}

.spinner {
    animation: spin 1s linear infinite;
}

脉冲效果

CSS
@keyframes pulse {
    0% {
        transform: scale(1);
        opacity: 1;
    }
    50% {
        transform: scale(1.1);
        opacity: 0.7;
    }
    100% {
        transform: scale(1);
        opacity: 1;
    }
}

.pulse {
    animation: pulse 2s infinite;
}

打字机效果

CSS
@keyframes typing {
    from {
        width: 0;
    }
    to {
        width: 100%;
    }
}

@keyframes blink {
    0%, 100% {
        border-color: transparent;
    }
    50% {
        border-color: black;
    }
}

.typewriter {
    overflow: hidden;
    border-right: 2px solid;
    white-space: nowrap;
    animation: typing 3s steps(40, end), blink 1s infinite;
}

动画事件

JavaScript可以监听动画的开始、结束、迭代和取消事件:

JavaScript
const element = document.querySelector('.animated-element');

// 动画开始
element.addEventListener('animationstart', function(event) {
    console.log('动画开始:', event.animationName);
});

// 动画结束
element.addEventListener('animationend', function(event) {
    console.log('动画结束:', event.animationName);
});

// 动画迭代
element.addEventListener('animationiteration', function(event) {
    console.log('动画迭代:', event.animationName);
});

// 动画取消
element.addEventListener('animationcancel', function(event) {
    console.log('动画取消:', event.animationName);
});

动画效果演示

Demo
当前动画:
状态: 未开始
迭代次数: 0
动画事件将显示在这里...

当前动画CSS代码:

CSS
/* 选择动画类型查看代码 */

动画性能优化

使用transform和opacity: 这些属性可以由GPU加速,性能更好。
避免布局抖动: 避免在动画中修改会影响布局的属性,如width、height、margin等。
使用will-change: 提前告知浏览器元素将要发生的变化,以便优化。
减少复合操作: 避免同时动画多个复杂属性。
CSS
/* 性能优化示例 */
.optimized-element {
    will-change: transform, opacity;
    animation: slideIn 1s ease;
}

/* 避免这样做 */
.unoptimized-element {
    animation: complexAnimation 1s ease; /* 可能包含布局属性 */
}

性能优化属性列表

性能优秀 性能一般 性能较差
transform color width
opacity background-color height
filter border-color margin
backdrop-filter font-size padding

动画与可访问性

减少动画偏好: 尊重用户的系统偏好设置,为偏好减少动画的用户提供替代方案。
CSS
/* 基础动画效果 */
.animated-element {
    animation: bounce 2s infinite;
}

/* 为偏好减少动画的用户移除动画 */
@media (prefers-reduced-motion: reduce) {
    .animated-element {
        animation: none;
    }
}

渐进增强动画

CSS
/* 基础样式 */
.element {
    opacity: 0;
}

/* 支持动画的设备应用动画 */
@media (prefers-reduced-motion: no-preference) {
    .element {
        animation: fadeIn 1s ease forwards;
    }
}

/* 不支持动画的设备直接显示 */
@media (prefers-reduced-motion: reduce) {
    .element {
        opacity: 1;
    }
}

现代动画技术

1. 自定义属性与动画

使用CSS自定义属性创建动态动画:

CSS
:root {
    --animation-duration: 1s;
    --animation-delay: 0s;
}

.element {
    animation: slideIn var(--animation-duration) ease var(--animation-delay);
}

2. 滚动驱动动画

CSS Scroll-Driven Animations(实验性功能):

CSS
@keyframes reveal {
    from {
        opacity: 0;
        transform: translateY(50px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.scroll-animation {
    animation: reveal linear;
    animation-timeline: view();
}

3. 视图过渡API

View Transitions API(实验性功能):

JavaScript
// 启用视图过渡
if (document.startViewTransition) {
    document.startViewTransition(() => {
        // 更新DOM
        updateTheDOMSomehow();
    });
}