找回密码
 立即注册
搜索
查看: 7|回复: 7

CSS关键帧动画初步 转帖马黑黑教程专版

[复制链接]

1477

主题

3151

回帖

1万

积分

管理员

积分
12684
发表于 昨天 23:35 | 显示全部楼层 |阅读模式
https://www.huachaowang.com/forum.php?mod=viewthread&tid=94914


CSS关键帧动画由 @keyframes 创建一个自定义名称的动画序列,再由元素对应的选择器通过 animation 属性调用动画。 一、创建CSS关键帧动画 创建CSS关键帧动画用 @keyframes 实现,语法结构: @keyframes 名称 {
    时间节点1 { CSS属性 }
    时间节点2 { CSS属性 }
    时间节点N { CSS属性 }
} @keyframes 创建的动画序列以一系列关键帧描述动画形态,包含时间节点和动画数据。时间节点可以使用百分比或关键字 from 和 to 表示,动画数据则是任意支持关键帧动画的单个或多个CSS属性。试看: /* 方法一 :百分比 */
@keyframes move {
    0% { left: 0px; top: 10px; }
    100% { left: 240px; top: 180px; }
}

/* 方法二 :关键字 */
@keyframes move {
    from { left: 0px; top: 10px; }
    to { left: 240px; top: 180px; }
} 上述两种关键帧动画的设计等价,但方法一更易于扩展:在0%~100% 之间可以加入任意多个时间节点用以描述更多的关键帧。方法二适用于简易动画,它只关心两个时间节点即 0% 和 100% 的动画状态。

1477

主题

3151

回帖

1万

积分

管理员

积分
12684
 楼主| 发表于 昨天 23:38 | 显示全部楼层
很多时候元素用于关键帧动画的对应CSS属性已经设置了初始值,若此,关键帧动画开始的时间节点可以省略(特别是基于关键字方法): /* 元素定义了 left和 top 初始值 */
.ball { position: absolute; left: 0px; top: 10px; }

/* keyframes 关键帧动画可以省略 from 关键字属性 */
@keyframes move {
    to { left: 240px; top: 180px; }
} 对于追求简洁代码需求而言,这是有效的方法,但一切应根据具体情况而定。

1477

主题

3151

回帖

1万

积分

管理员

积分
12684
 楼主| 发表于 昨天 23:39 | 显示全部楼层
二、运行CSS关键帧动画
CSS关键帧动画由元素运行,通过元素对应CSS选择器的 animation 属性进行设置。animation 属性语法结构如下: /* 红色参数必须,其余可选(缺省时使用默认值) */
    animation: ①动画名称 ②周期时长 ③时间函数 ④延时时间 ⑤运行次数 ⑥运动方向 ⑦结束状态 ⑧播放状态
/* 应用举例 :①move动画,②6秒一周期,③匀速,④延时0秒,⑤运行一次,⑥正向,⑦保留最后状态,⑧运行 */
animation: move 6s linear 0s 1 normal forwards running;
/* 因为 0s、normal、running 属性值都是默认值,可以简化为 */
animation: move 6s linear 1 forwards; animation 是一个简写属性,它包含多个 animation-* 属性: 1. animation-name :由 @keyframes 创建的动画名称,支持单个、多个 2. animation-duration :动画周期时长,即完成一个动画周期所需的时间,时间单位 3. animation-timing-function : 时间函数,即动画在每个周期的持续时间内如何进行,例如匀速、先快后慢、两头慢中间快或自定义运动时间曲线等等(文末附详细列表) 4. animation-delay :动画延时时间,本质指动画执行之前等待的时间量,支持正(延后)负(提前)数,时间单位 5. animation-iteration-count :动画运行次数,小于等于0表示不运行,infinite 表示永久运行 6. animation-direction :运动方向,即播放动画的方向与 @keyframes 时间节点指向的关系,值有 normal(默认,正向)、reverse(反向)、alternate(往复)、alternate-reverse(反向往复) 7. animation-fill-mode :动画结束时的状态,确切以言之,该属性设置 CSS 动画在执行之前和之后如何将样式应用于其目标。默认值是 none,可选值 forwards(保留最后帧状态)、backwards(首帧状态) 8. animation-play-state :动画播放状态,设置动画播放(running)或暂停(paused)


1477

主题

3151

回帖

1万

积分

管理员

积分
12684
 楼主| 发表于 昨天 23:41 | 显示全部楼层
CSS关键帧动画由 @keyframes 创建一个自定义名称的动画序列,再由元素对应的选择器通过 animation 属性调用动画。
一、创建CSS关键帧动画
创建CSS关键帧动画用 @keyframes 实现,语法结构:
@keyframes 名称 {    时间节点1 { CSS属性 }    时间节点2 { CSS属性 }    时间节点N { CSS属性 }}
@keyframes 创建的动画序列以一系列关键帧描述动画形态,包含时间节点和动画数据。时间节点可以使用百分比或关键字 from 和 to 表示,动画数据则是任意支持关键帧动画的单个或多个CSS属性。试看:
/* 方法一 :百分比 */@keyframes move {    0% { left: 0px; top: 10px; }    100% { left: 240px; top: 180px; }}/* 方法二 :关键字 */@keyframes move {    from { left: 0px; top: 10px; }    to { left: 240px; top: 180px; }}
上述两种关键帧动画的设计等价,但方法一更易于扩展:在0%~100% 之间可以加入任意多个时间节点用以描述更多的关键帧。方法二适用于简易动画,它只关心两个时间节点即 0% 和 100% 的动画状态。
很多时候元素用于关键帧动画的对应CSS属性已经设置了初始值,若此,关键帧动画开始的时间节点可以省略(特别是基于关键字方法):
/* 元素定义了 left和 top 初始值 */.ball { position: absolute; left: 0px; top: 10px; }/* keyframes 关键帧动画可以省略 from 关键字属性 */@keyframes move {    to { left: 240px; top: 180px; }}
对于追求简洁代码需求而言,这是有效的方法,但一切应根据具体情况而定。
二、运行CSS关键帧动画
CSS关键帧动画由元素运行,通过元素对应CSS选择器的 animation 属性进行设置。animation 属性语法结构如下:
/* 红色参数必须,其余可选(缺省时使用默认值) */    animation: ①动画名称 ②周期时长 ③时间函数 ④延时时间 ⑤运行次数 ⑥运动方向 ⑦结束状态 ⑧播放状态/* 应用举例 :①move动画,②6秒一周期,③匀速,④延时0秒,⑤运行一次,⑥正向,⑦保留最后状态,⑧运行 */animation: move 6s linear 0s 1 normal forwards running;/* 因为 0s、normal、running 属性值都是默认值,可以简化为 */animation: move 6s linear 1 forwards;
animation 是一个简写属性,它包含多个 animation-* 属性:
  • animation-name :由 @keyframes 创建的动画名称,支持单个、多个
  • animation-duration :动画周期时长,即完成一个动画周期所需的时间,时间单位
  • animation-timing-function : 时间函数,即动画在每个周期的持续时间内如何进行,例如匀速、先快后慢、两头慢中间快或自定义运动时间曲线等等(文末附详细列表)
  • animation-delay :动画延时时间,本质指动画执行之前等待的时间量,支持正(延后)负(提前)数,时间单位
  • animation-iteration-count :动画运行次数,小于等于0表示不运行,infinite 表示永久运行
  • animation-direction :运动方向,即播放动画的方向与 @keyframes 时间节点指向的关系,值有 normal(默认,正向)、reverse(反向)、alternate(往复)、alternate-reverse(反向往复)
  • animation-fill-mode :动画结束时的状态,确切以言之,该属性设置 CSS 动画在执行之前和之后如何将样式应用于其目标。默认值是 none,可选值 forwards(保留最后帧状态)、backwards(首帧状态)
  • animation-play-state :动画播放状态,设置动画播放(running)或暂停(paused)
属性较多,可以根据需要取舍,逐个设置时顺序不论:
.ball {    /* ... 这里是其它代码 */    animation-name: move;    animation-duration: 6s;    animation-timing-function: linear;    animation-iteration-count: 1;    animation-fill-mode: forwards;}
建议尽可能使用 animation 简写属性设置动画。
三、动画实例(一)元素平移运行代码<style>    .rect {        width: 40px;        height: 40px;        background: cyan;        transform: translate(0,100px);        /* 匀速、8秒一个周期、永动、往复(来、回各算一个周期) */        animation: move linear 8s infinite alternate;    }    /* 动画 :水平移动 */    @keyframes move {        to { transform: translate(800px,100px); }    }</style><div class="rect"></div>


1477

主题

3151

回帖

1万

积分

管理员

积分
12684
 楼主| 发表于 昨天 23:44 | 显示全部楼层
(二)元素旋转 运行代码  <style>
    .rect {
        margin: 200px;
        width: 180px;
        height: 180px;
        background: lightgreen;
        /* 慢-快-慢、5秒一个周期、2秒后开始、转3圈 */
        animation: rot 5s ease-in-out 2s 3;
    }

    /* 动画 :旋转360度 */
    @keyframes rot {
        100% { transform: rotate(360deg); }
    }
</style>

<div class="rect"></div> (三)元素形状变化(分步) 运行代码  <style>
    .rect {
        margin: 100px;
        width: 300px;
        height: 300px;
        border: 4px dotted purple;
        /* 匀速、6秒一个周期、分四步(阶跃运动)、保留最后状态 */
        animation: rot 6s steps(4, end) forwards;
        /* animation: rot 6s steps(3, start) forwards; */
    }

    /* 动画 :从矩形变成圆形 */
    @keyframes rot {
        0% { border-radius: 0%; }
        100% { border-radius: 50%; }
    }
</style>

<div class="rect"></div> (四)多个元素转圈圈 运行代码  <style>
    /* 父元素 */
    .pa { margin: 100px auto; width: 300px; height: 300px; border-radius: 50%; border: 3px dashed gray; position: relative; }

    /* 子元素 */
    .rect {
        position: absolute;
        width: 60px;
        height: 60px;
        background: tan;
        transform-origin: 150px 150px; /* 运动中心点坐标设在父元素中心点 */
        /* 6秒一个周期、匀速、运行一百次 */
        animation: ring 6s linear 100;
    }

    /* 第2、3子元素提前运行动画 */
    .rect:nth-of-type(2) { animation-delay: -2s; }
    .rect:nth-of-type(3) { animation-delay: -4s; }

    /* 动画 :旋转一周 */
    @keyframes ring {
        to { transform: rotate(1turn); }
    }
</style>
<div class="pa">
    <div class="rect"></div>
    <div class="rect"></div>
    <div class="rect"></div>
</div> (五)元素做椭圆运动 运行代码  <style>
    /* 本例 offset-path 支持百分比,所以是自适应窗口尺寸的 */
    .ball {
        width: 80px;
        height: 80px;
        border-radius: 50%;
        background: linear-gradient(20deg, cyan, green);
        /* 椭圆路径 :以容器(这里是body)宽高各45%做长短轴半径、圆心在body中心点 */
        offset-path: ellipse(45% 45% at 50% 50%);
        animation: move linear 20s infinite;
    }
    /* 动画 :在路径中偏移 */
    @keyframes move {
        0% { offset-distance: 0%; }
        100% { offset-distance: 100%; }
    }
</style>

<div class="ball"></div>

1477

主题

3151

回帖

1万

积分

管理员

积分
12684
 楼主| 发表于 昨天 23:45 | 显示全部楼层
四、使用JS简单控制关键帧动画 对关键帧动画最常见的需求是动画的播放与暂停操作。这可以使用JS直接操作元素的 animation-play-state 属性:前面已经提到过,属性值 running 表示播放、paused 表示暂停。
看实例:
🔹JS简单控制CSS关键帧动画 运行代码  <style>
    .kite {
        cursor: pointer;
        transform-origin: 100% 0;
        animation: skew ease-out 0.85s infinite alternate;
    }
    /* 动画 :在路径中偏移 */
    @keyframes skew {
        to { transform: skew(5deg); }
    }
</style>

<img class="kite" src="https://638183.freep.cn/638183/small/kite.png" alt="" title="点击播放/暂停" />

<script>
    const kite = document.querySelector('.kite');
    kite.onclick = () => {
        // 使用 getAnimations API 获取元素的CSS动画相关信息
        const { playState } = kite.getAnimations()[0];
        // 如果动画运行中则暂停
        if (playState === 'running') {
            kite.style.setProperty('animation-play-state', 'paused');
        // 反之继续播放
        } else {
            kite.style.setProperty('animation-play-state', 'running');
        }
    };
</script>


1477

主题

3151

回帖

1万

积分

管理员

积分
12684
 楼主| 发表于 昨天 23:46 | 显示全部楼层
Element.getAnimations() API 不是必须的,上例用到它主要是为了判断元素运行动画的状态(running或paused),从而决定点击图片时动画应暂停还是继续。在实际应用场景中,可以根据诸多情况来决定动画处于何种状态,例如音画帖中关键帧动画与音频的播放、暂停状态的紧密关联。另外,如果由于某种原因不方便直接操作CSS动画播放状态属性,我们可以使用 CSS 变量来代替 animation-play-state 的属性值,直接操作该变量,这样就不用针对每一个元素进行操作,而是批量操作所有使用了该 CSS 变量的所有元素: /* CSS 代码 :父元素定义 --state 变量值 */
.pa {
    --state: running;
}
/* 子元素动画简写属性使用 --state 变量给 animation-play-state 属性赋值 */
.son {
    animation: skew ease-out 0.85s infinite alternate var(--state);
}

// JS代码 :批量操作 .pa 下的所有使用了 var(--state) 的动画
const pa = document.querySelector('.pa');
// 如果要播放动画:
pa.style.setProperty('--state', 'running');
// 如果要暂停动画:
pa.style.setProperty('--state', 'paused'); 对于非无穷大的动画播放次数,有时候可能需要监听动画的开始、结束动作,以便决定动画流程的下一步环节,这时有两个JS事件可用:animationstart(动画开始)和 animationend(动画结束): 🔹JS监听动画开始和动画结束事件 运行代码  <style>
    .rect { left: 20px; top: 100px; width: 200px; height: 100px; display: grid; place-items: center; background: wheat; position: absolute; }
    .ani1 { animation: move linear 16s forwards; }
    .ani2 { animation: move linear 8s reverse forwards; }
    @keyframes move {
        to { left: calc(100% - 220px); }
    }
</style>

<div class="rect">点击开始动画</div>

<script>
    const rect = document.querySelector('.rect');
    const anis = ['ani1', 'ani2']; // 动画数组
    let idx = 0; // 动画运行计数

    // 动画开始事件
    rect.onanimationstart = () => rect.textContent = `动画 :${anis[idx % 2]}`;

    // 动画结束事件
    rect.onanimationend = () => {
        rect.classList.remove(anis[idx % 2]);
        idx += 1;
        setTimeout( () => rect.classList.add(anis[idx % 2]), 0);
    };

    rect.onclick = () => {
        // 若动画尚未开始
        if (!rect.getAnimations()[0]) {
            rect.classList.add(anis[idx]); // 开始动画
        // 若动画已经开始
        } else {
            const { playState } = rect.getAnimations()[0]; // 获取动画状态
            // 暂停或继续动画
            rect.style.setProperty(
                'animation-play-state',
                playState === 'running' ? 'paused' : 'running'
            );
        }

    };
</script> JS 操作 CSS 关键帧动画远不止这些,限于篇幅,本文点到而止。

1477

主题

3151

回帖

1万

积分

管理员

积分
12684
 楼主| 发表于 昨天 23:49 | 显示全部楼层
附:animation-timing-function 属性值及其含义 属性值 属性值说明  


截取图片_20260727234810.png
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

协同嘉业科技有限公司 ( 京ICP备2024053108号-1 )

GMT+8, 2026-7-28 05:05 , Processed in 0.101700 second(s), 48 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表