金字塔css动画解析

第一次见到这个动图的时候,比较惊讶,心想这真是css能实现的吗?后面对css动画有了一定学习了解后,才发现其实css的强大超乎想象👍,而这仅仅是冰山一角。话不多说,接下来我将详细解析如何通过代码一步步实现这个动画。
元素拆分
对于整个动画的实现,我通常不会一开始就着手考虑 CSS 动画如何实现,而是优先分析 HTML 元素的结构构成。以上这个金字塔图片,可以拆分为几个独立的元素。

上面我用数字标出来分别代表天空、地面、太阳、金字塔左面、金字塔右面、阴影6个元素。
基础图形绘制
背景
首先绘制出承载这些元素的背景,包括一个偏黑色的正方形背景和位于正中心的圆形。其中,圆形通过 border-radius: 50%
实现。
1 2 3
| <div class="frame"> <div class="circle"></div> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| .frame { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); height: 400px; width: 400px; background: #272C34; border-radius: 4px; box-shadow: 1px 2px 10px 0 rgba(0, 0, 0, 0.3); }
.circle { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); height: 180px; width: 180px; background: #fff; border-radius: 50%; }
|

天空&地面
从图中可以看出,天空的高度相较于地面更大一些。我们可以设计两个高度不同的 div
,通过设置它们的高度比例来保证完整填充父元素。
1 2 3 4
| <div class="circle"> <div class="sky"></div> <div class="ground"></div> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| .sky { position: absolute; top: 0; left: 0; right: 0; height: 124px; background: #7DDFFC; }
.ground { position: absolute; bottom: 0; left: 0; right: 0; top: 124px; background: #F0DE75; }
|

之前的圆形没有显示出来,此时可以在父元素circle的样式中设置 overflow: hidden
,将超出圆形范围的部分隐藏即可

太阳
同样是绘制一个圆形,先通过绝对定位将其固定在指定位置
1 2 3
| <div class="circle"> <div class="sun"></div> </div>
|
1 2 3 4 5 6 7 8 9
| .sun{ position: absolute; top:20px; left:10px; width: 34px; height: 34px; border-radius: 50%; background: #FFEF00; }
|

金字塔
通过两个三角形拼接,可以模拟金字塔的立体效果。利用 clip-path: polygon
绘制三角形,并设置不同的背景颜色以实现阴影效果。
1 2 3 4 5
| <div class="circle"> <div class="side-left"></div> <div class="side-right"></div> </div>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| .side-left{ position: absolute; top: 67px; left: 35px; height: 57px; width: 116px; background: #F4F4F4; }
.side-right{ position: absolute; top: 67px; left: 93px; height: 57px; width: 58px; background: #DDDADA; }
|

使用clip-path:polygon
绘制出三角形,给出三角形三个点坐标即可。
1 2 3 4 5 6 7
| .side-left{ clip-path: polygon(0% 100%, 100% 100%, 50% 0%); }
.side-right{ clip-path: polygon(30% 100%, 100% 100%, 0% 0%); }
|
这里以side-left元素为例,三个点分别表示左下角到右上角坐标,第一个点(x=0%, y=100%)
表示容器宽度的 0%(最左侧)和高度的 100%(最底部),即容器的左下角。第二个点对应右下角,第三个点则为顶部中间。

最终叠加效果展示金字塔效果如下图

阴影
金字塔的地面阴影同样通过绘制一个三角形来完成。并设置适当的透明度,模拟真实的光影效果。
1 2 3
| <div class="circle"> <div class="shadow"></div> </div>
|
1 2 3 4 5 6 7 8 9 10
| .shadow{ position: absolute; z-index: 2; top: 124px; left: -80px; height: 30px; width: 360px; background: rgba(0,0,0,0.2); clip-path: polygon(115px 0%, 231px 0%, 80% 100%); }
|

超出部分被隐藏后,效果如下。

至此,一个由多个元素组成的金字塔页面已成功绘制完成。接下来,我们将为其加入动画效果,使金字塔动起来
动画
在日常开发中,CSS 动画使用频率相对较低,对我来说是这样的(
因此可能需要专门花时间学习。然而,接下来的实现可能需要对动画有一定基础了解
本次动画的缓动函数统一采用了 ease-out
,具有以下效果:
- 缓慢启动:动画在起始阶段速度较慢,提供平滑的启动感。
- 逐渐加速:中间阶段速度逐渐加快,形成流畅的过渡。
- 平稳停止:接近终点时速度快速减缓,最终平稳结束。
接下来,让我们逐步为页面中的各个元素加入动画效果吧!
夕阳下沉
首先定义一下太阳运动的动画帧
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| @keyframes sun-goes-down { 0% { background: #F57209; transform: rotate(-70deg); }
30% { background: #FFEF00; transform: rotate(-28deg); }
70% { background: #FFEF00; }
100% { background: #F57209; transform: rotate(70deg); } }
|
这里旋转角度,需要选择一个旋转参考变换原点
1 2 3 4 5 6
| .sun{ transform-origin: 50% 400%; animation: sun-goes-down 4s ease-out infinite; }
|
为什么选择 50% 400%
:
- 选择水平居中 (
50%
) 是为了让旋转时太阳的位置在视觉上不会偏移,即太阳始终在水平中心线。
- 选择
400%
作为垂直方向的参考点,是为了让太阳看起来从非常高的地方下落,模拟太阳从天空中下沉的效果。这样,动画中的旋转看起来就像太阳从远处的高空落下,而不是简单的围绕自己中心旋转。
夜幕降临
给天空也定义一个动画,主要改变其背景颜色,实现天空由明亮到黑暗,模拟夜晚来临。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| .sky{ animation: sky-turns-black 4s ease-out infinite; }
@keyframes sky-turns-black { 0% { background: #272C34; }
30% { background: #7DDFFC; }
70% { background: #7DDFFC; }
100% { background: #272C34; } }
|
沙漠褪色
沙地的颜色也跟随动画过程中逐渐变化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| .ground { animation: fading-sand 4s ease-out infinite; }
@keyframes fading-sand { 0% { background: #272C34; }
30% { background: #F0DE75; }
70% { background: #F0DE75; }
100% { background: #272C34; } }
|
上述三个动画的效果图

金字塔阴影
在太阳运行的过程中,金字塔的阴影也会随之变化。随着时间推移,阴影从右侧逐渐移动至左侧,呈现出动态光照效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| .side-left { animation: pyramid-shading 4s ease-out infinite; }
.side-right { animation: pyramid-shading 4s ease-out infinite reverse; }
@keyframes pyramid-shading { 0% { background: #272C34; }
30% { background: #F4F4F4; }
70% { background: #DDDADA; }
100% { background: #272C34; } }
|

地面影动
在太阳运行的过程中,地面上的金字塔阴影也会随之变化,模拟真实光照下的动态投影效果。阴影的形态不仅会随着光源位置拉伸或收缩,还会在不同角度之间过渡。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| .shadow{ animation: shadow-on-the-floor 4s ease-out infinite; }
@keyframes shadow-on-the-floor { 0% { transform: scaleY(0); clip-path: polygon(115px 0%, 231px 0%, 100% 100%); }
30% { transform: scaleY(1); clip-path: polygon(115px 0%, 231px 0%, 80% 100%); }
55% { transform: scaleY(0.4); }
75% { transform: scaleY(1); }
100% { transform: scaleY(0); clip-path: polygon(115px 0%, 231px 0%, 0% 100%); } }
|
去掉遮挡背景和超出隐藏的部分后效果图

总结
将上述动画效果整合在一起,便形成了文章开头展示的 金字塔动态光影效果。随着太阳的位置变化,金字塔的阴影与地面投影同步变换。完整的代码已上传至GitHub :📌 金字塔源码
最终效果:
