手把手教你实现一个小飞机

1,000 阅读4分钟

前言

这次趁着周末休息的时间,弄了一个用 CSS实现的直升机的动画效果。整个实现过程比较简单,大家可以先看到下面的效果预览部分,十分简单,没有花里胡哨的技巧。话不多说,咱们直接进入主题。

效果预览

最终实现的相关效果如下。

HTML部分

首先我们看到HTML部分,相关代码如下。

 <div class="plane">
        <div class="fans">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
        </div>
        <div class="wheels">
            <span class="wheel left"></span>
            <span class="wheel right"></span>
        </div>
    </div>

这里创建了一个飞机动画的基本结构,包含三个主要部分,首先看到<div class="plane">,这里是飞机的主体容器,紧接着是螺旋桨部分 (<div class="fans">),包含4个<span>元素,代表螺旋桨的叶片,每个<span>会通过CSS样式形成螺旋桨的各个叶片。

最后是起落架部分 (<div class="wheels">),包含左右两个轮子 (<span class="wheel left"><span class="wheel right">),每个轮子元素后续会通过CSS样式形成飞机的轮子和支撑结构。

CSS部分

接着我们看到CSS部分,首先我们看到飞机容器的样式,相关代码如下。

.plane {
    font-size: 10px;
    width: 28em;
    height: 13em;
    display: flex;
    justify-content: center;
    position: relative;
    color: black;
    /* wings */
    background: 
        linear-gradient(currentColor, currentColor)
            no-repeat center top / 100% 0.5em,
        linear-gradient(currentColor, currentColor)
            no-repeat center 4em / 90% 0.4em;
    animation: 
        plane-rotating 10s infinite,
        fly 5s infinite;
}

使用flex布局,水平居中内容,使用线性渐变创建出机翼样式,并且设置一些动画效果,旋转动画:持续10秒,无限循环;飞行动画:持续5秒,无限循环。

接着看到设置的飞机动画效果,相关代码如下。

@keyframes plane-rotating {
    10%, 30%, 50% {transform: rotate(0deg);}
    20% {transform: rotate(-4deg);}     
    80% {transform: rotate(8deg);}          
    100% {transform: rotate(-1turn);}
}
@keyframes fly {
    10%, 50%, 100% {top: 0;}    
    25% {top: 1em;}            
    75% {top: -1em;}            
}

这里创造了两个具有逼真飞行效果的飞机动画,包含旋转和上下浮动两种运动模式。在plane-rotating动画中,在10%、30%、50%时间点保持水平,在20%时间点向左倾斜4度,在80%时间点向右倾斜8度,在100%时间点完成一整圈旋转(逆时针)。

fly动画中,在10%、50%、100%时间点保持在原始位置,在25%时间点向下移动1em(10px),在75%时间点向上移动1em(10px)。

接着我们看到四叶螺旋桨的样式,相关代码如下。

.fans {
    width: 11em;
    height: 11em;
    background: radial-gradient(currentColor 2.5em, transparent 2.5em);
}
.fans span {
    width: inherit;
    height: 50%;
    background-color: hsla(100, 100%, 100%, 0.4);
    border-radius: 50% 50% 0 0 / 100% 100% 0 0;
    transform-origin: bottom;
    transform: rotate(calc((var(--n) - 1) * 90deg));
    animation: fans-rotating 0.8s linear infinite;
    animation-delay: calc(var(--n) * 0.1s);
}
@keyframes fans-rotating {
    to {transform: rotate(-1turn);}
}

从代码中可以看出,半圆形叶片是使用特殊border-radius语法border-radius: 50% 50% 0 0 / 100% 100% 0 0创建出来的半圆形顶部。使用CSS变量(--n) 控制每个叶片的角度和动画延迟,需要配合额外的CSS为每个span设置不同的--n值。使用transform-origin: bottom确保叶片围绕底部中心旋转。使用calc((var(--n) - 1) * 90deg)将4个叶片均匀分布(0°, 90°, 180°, 270°)。最后使用calc(var(--n) * 0.1s)为每个叶片设置不同的延迟,创建连续旋转效果。

综上所述,这里创建了一个四叶片螺旋桨,每个叶片从底部中心点旋转出来,并通过CSS动画实现连续旋转效果,模拟飞机螺旋桨的工作状态。

最后我们看到轮子的样式,相关代码如下。

.wheels {
    width: 16em;
    height: 2em;
    bottom: 0;
    display: flex;
    justify-content: space-between;
}
.wheel {
    position: relative;
    width: 1em;
    height: inherit;
    background-color: currentColor;
    border-radius: 0.5em;
    display: flex;
    justify-content: center;
}
.wheel::before {
    width: 0.2em;
    height: 8em;
    background-color: currentColor;
    transform-origin: bottom;
    bottom: 1em;
    z-index: -1;
}

对于整体的结构,使用display: flexjustify-content: space-between让两个轮子平均分布在起落架容器两端,使用::before伪元素创建轮子的支撑杆,无需额外HTML元素。position: relative为轮子创建定位上下文,position: absolute让支撑杆相对于轮子定位,bottom: 1em将支撑杆底部定位在轮子内部。

综上所述,这里创建了一个完整的飞机起落架结构,包含两个轮子和它们的支撑杆,形成完整的V形起落架结构。

总结

以上就是整个效果的实现过程了,代码简单易懂。另外,感兴趣的小伙伴们还可以在现有基础上发散思维,比如增加点其他效果,或者更改颜色等等。关于该效果如果大家有更好的想法欢迎在评论区分享,互相学习。最后,完整代码在码上掘金里可以查看,如果有什么问题大家在评论区里讨论~