关键帧动画

animation 属性设定了元素的动画效果,与过渡动画不同的时,动画可以被设定为一直存在,无需在属性值改变时才触发。

<div class="box"></div>
<style>
    .box {
        width: 100px;
        height: 50px;
        background-color: teal;
        animation: 2s infinite effect;
    }

    @keyframes effect {
        to {
            width: 300px;
        }
    }
</style>

$$demo

<div class="box"></div>

<style>

.box {

width: 100px;

height: 50px;

background-color: teal;

animation: 2s infinite effect;

}

@keyframes effect {

to {

width: 300px;

}

}

</style>

$$

animation 是多个样式属性的缩写:

  • animation-name:动画关键帧名。
  • animation-duration:动画时长。
  • animation-timing-function:动画曲线。
  • animation-delay:延迟时长。
  • animation-iteration-count:播放次数。
  • animation-direction:播放方向。
  • animation-play-state:播放状态。

animation-name

animation-name 设定了动画关键帧名,搭配 @keyframes 指定一系列关键帧。

<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/zYpKRLV?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>

@keyframes

@keyframes 中使用百分比来定义在不同阶段的动画效果,也有关键字取值:

  • from:等同于 0%。
  • to:等同于 100%。

$$tip

未设置 fromto 的情况下,它们的样式等同于元素设定的样式值。

$$

<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/jOYMZoe?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>

animation-duration

animation-duration 定义了动画播放的时长,默认值 0s ,取值是时间单位

<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/MWrjVqa?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>

animation-timing-function

animation-timing-function 定义了动画的变化曲线,默认值是 ease ,有以下取值:

<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/GRyjxPY?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>

animation-delay

animation-delay 决定了动画延迟播放的时长,默认值是 0s ,取值是时间单位

<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/QWaKmRW?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>

animation-iteration-count

animation-iteration-count 定义了动画的播放次数,默认值是 1 ,有以下取值:

  • 非负数字:播放的次数,可以为小数,比如 0.5 就表示播放一半的动画效果。
  • infinite:无限次循环。

animation-direction

animation-direction 决定了动画的播放方向,有以下取值:

  • normal:默认值,正向播放,播放结束后返回最初的状态。
  • alternate:正反交替,正向开始,动画正向与反向交替播放。
  • reverse:反向播放。
  • alternate-reverse:正反交替,反向开始,动画正向与反向交替播放。

<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/rNpMvOy?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>

animation-play-state

animation-play-state 定义了元素的播放状态,有两个取值:

  • running:默认值,正常播放。
  • paused:暂停。

<iframe height="300" style="width: 100%" scrolling="no" title="flexbox" src="https://codepen.io/3yya/embed/qBpaYNo?default-tab=css%2Cresult&editable=true&theme-id=light" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"></iframe>


练习

  1. 实现以下的实例效果。

$$demo

<div class="box">三眼鸭的编程教室</div>

<style>

.box {

display: inline-block;

padding: 10px 20px;

border: 4px solid black;

animation-name: roll;

animation-duration: 4s;

animation-iteration-count: infinite;

}

@keyframes roll {

to {

transform: rotateY(360deg);

}

}

</style>

$$

$$answer

<div class="box">三眼鸭的编程教室</div>

<style>
    .box {
        display: inline-block;

        padding: 10px 20px;

        border: 4px solid black;

        animation-name: roll;
        animation-duration: 4s;
        animation-iteration-count: infinite;
    }

    @keyframes roll {
        to {
            transform: rotateY(360deg);
        }
    }
</style>

$$

  1. 实现以下的时钟效果。 $$tip

transform-origin 可以设置变换的原点。

$$ $$demo <div class="dial"> <div class="second pointer"></div> <div class="minute pointer"></div> </div> <style> .dial { width: 200px; height: 200px;

    border-radius: 50%;
    border: 10px solid black;

    position: relative;
}

.pointer {
    /* 指针尾部多余的长度 */
    --out-len: 20px;

    /* 指针的宽度 */
    --pointer-width: 10px;

    width: var(--pointer-width);

    position: absolute;

    left: calc(50% - var(--pointer-width) / 2);
    bottom: calc(50% - var(--out-len));

    /* 旋转的原点: x 为中心, y 为元素的长度减去尾部的长度 */
    transform-origin: center calc(100% - var(--out-len));

    animation-name: effect;

    /* 线性播放动画效果 */
    animation-timing-function: linear;
    /* 无限循环 */
    animation-iteration-count: infinite;
}

.second {
    /* 45% 的长度加上指针尾部的长度 */
    height: calc(45% + var(--out-len));

    background-color: red;

    /* 每圈 60 秒 */
    animation-duration: 60s;

    /* 秒针在时针之上 */
    z-index: 99;
}

.minute {
    /* 30% 的长度加上指针尾部的长度 */
    height: calc(30% + var(--out-len));

    background-color: teal;

    position: absolute;

    /* 每圈 3600 秒 */
    animation-duration: 3600s;

    z-index: 0;
}

@keyframes effect {
    to {
        transform: rotate(360deg);
    }
}

</style>

$$

$$answer

<div class="dial">
    <div class="second pointer"></div>
    <div class="minute pointer"></div>
</div>
<style>
    .dial {
        width: 200px;
        height: 200px;

        border-radius: 50%;
        border: 10px solid black;

        position: relative;
    }

    .pointer {
        /* 指针尾部多余的长度 */
        --out-len: 20px;

        /* 指针的宽度 */
        --pointer-width: 10px;

        width: var(--pointer-width);

        position: absolute;

        left: calc(50% - var(--pointer-width) / 2);
        bottom: calc(50% - var(--out-len));

        /* 旋转的原点: x 为中心, y 为元素的长度减去尾部的长度 */
        transform-origin: center calc(100% - var(--out-len));

        animation-name: effect;

        /* 线性播放动画效果 */
        animation-timing-function: linear;
        /* 无限循环 */
        animation-iteration-count: infinite;
    }

    .second {
        /* 45% 的长度加上指针尾部的长度 */
        height: calc(45% + var(--out-len));

        background-color: red;

        /* 每圈 60 秒 */
        animation-duration: 60s;

        /* 秒针在时针之上 */
        z-index: 99;
    }

    .minute {
        /* 30% 的长度加上指针尾部的长度 */
        height: calc(30% + var(--out-len));

        background-color: teal;

        position: absolute;

        /* 每圈 3600 秒 */
        animation-duration: 3600s;

        z-index: 0;
    }

    @keyframes effect {
        to {
            transform: rotate(360deg);
        }
    }
</style>

$$