纯CSS制作一个小动画

462 阅读2分钟

这是我参与8月更文挑战的第22天,活动详情查看:8月更文挑战

问题起源

前几天不知道写什么,在沸点上问XDM前端CSS还有什么画起来有点儿意思的:

CSS不知道写啥了,兄弟们给出道题目吧

几位好兄弟说,用CSS制作一个小动画吧。今天来完成以下兄弟们的小心愿。

那么如何用CSS制作动画呢?

CSS动画的关键属性:transition-delay/animation-delay

深入浅出的阮一峰大佬有一篇文章“CSS动画简介”详细介绍了CSS动画涉及的各个细节,尤其是CSS实现动画的两个重要属性:

  1. transition
  2. animation

实现连续动画的一个关键是如何按照指定顺序连接多个效果——transition-delayanimation-delay

animation是为了解决tansition的某些问题而产生的,因此我们不使用transition而使用animation来达到我们的动画目的。

CSS动画关键属性:@keyframes animation-name

使用animation后,我们可以通过在@keyframes animation-name中定义一个动画的多个阶段,从而实现动画效果。

做一个什么动画呢?

在文章“纯CSS绘制太极图”中,我们绘制了一个太极图,太极图转动起来才好看,因此,让太极图转动起来作为我们动画中的第一个动画效果:

动画.gif

第二个动画我们做什么呢?

我们让太极图上的上下两个小圆逐渐向圆心合并,以此实现类似逆向的“太极生两仪”,“两仪复太极”。

最终效果如下图:

动画.gif

源代码如下。

<!DOCTYPE html>
<title>太极图</title>

<body class="my-body">
    <div class="taiji-left">
        <div class="taiji-top"></div>
    </div>
    <div class="taiji-right">
        <div class="taiji-bottom"></div>
    </div>
</body>
<style>
    body  {
        width: 100vw;
        height: 100vh;
        background: lightblue;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: center;
    }
    
    .taiji-left {
        height: 400px;
        width: 200px;
        background: black;
        border-radius: 200px 0 0 200px ;
        position: relative;
    }
    .taiji-right {
        height: 400px;
        width: 200px;
        background: white;
        border-radius: 0 200px 200px 0;
        position: relative;
    }

    .taiji-top {
        border: 75px solid black;
        width: 50px;
        height: 50px;
        background: white;

        position: absolute;
        top: 0;
        right: -100px;
        border-radius: 50%;
        z-index: 2;
    }

    .taiji-bottom {
        border: 75px solid white;
        width: 50px;
        height: 50px;
        background: black;

        position: absolute;
        bottom: 0;
        left: -100px;
        border-radius: 50%;
    }

    .my-body {
        animation: rotate 5s linear forwards;
    }
    .taiji-top {
        animation-name: movetop, colorchangetop;
        animation-duration: 5s, 5s;
        animation-delay: 5s, 10s;
        animation-timing-function: linear, linear;
        animation-iteration-count: 1;
        animation-fill-mode: forwards;
    }
    .taiji-bottom {
        animation-name: movebottom, colorchangebottom;
        animation-duration: 5s, 5s;
        animation-delay: 5s, 10s;
        animation-timing-function: linear, linear;
        animation-iteration-count: 1;
        animation-fill-mode: forwards;
    }
    @keyframes rotate {
        0% {
            transform: rotate(0deg);
        }
        100% {
            transform: rotate(360deg);
        }
    }
    @keyframes movetop {
        0% {
            top: 0;
        }
        100% {
            top: 100px;
        }
    }
    @keyframes movebottom {
        0% {
            bottom: 0;
        }
        100% {
            bottom: 100px;
        }
    }
    @keyframes colorchangetop {
        0% {
            opacity: 1;
        }
        100% {
            opacity: 0.5;
        }
    }
    @keyframes colorchangebottom {
        0% {
            opacity: 1;
        }
        100% {
            opacity: 0.5;
        }
    }
</style>
</html>

总结

  1. 需要注意对同一个组件使用两个动画时的书写方式:不是写两遍animation,而是需要分开依次写各个动画的各个属性,如:
.taiji-bottom {
        animation-name: movebottom, colorchangebottom;
        animation-duration: 5s, 5s;
        animation-delay: 5s, 10s;
        animation-timing-function: linear, linear;
        animation-iteration-count: 1;
        animation-fill-mode: forwards;
    }
  1. 动画的连接效果使用animation-delay来保证执行顺序。