纯css实现一个沙漏动画
说在前面
沙漏大家都见过吧,使用js的话相信大家都能很轻易地实现一个沙漏动画吧,今天我们纯css来实现一个试试。
在线体验
码上掘金
codePen
代码实现
html
<div class="container">
<div class="hourglass">
<div class="frame"></div>
<div class="glass"></div>
<div class="sand-top-stroke"></div>
<div class="sand-top"></div>
<div class="sand-bottom-stroke"></div>
<div class="sand-bottom"></div>
<div class="sand-flow"></div>
<div class="sand-drop"></div>
<div class="glass-reflection"></div>
</div>
</div>
- container:包裹整个沙漏,调整整个沙漏的定位
- hourglass:沙漏的主容器
- frame:沙漏的外框,一个木架子
- sand-top-stroke、sand-bottom-stroke:存放沙子的玻璃容器
- sand-top、sand-bottom:上下部分的沙子
- sand-flow:连接上下两部分沙漏的管道
- sand-drop:滴落的沙子
- glass-reflection:添加一个玻璃反光效果
css
通用变量
:root {
--rotateTime: 10s;
}
定义沙漏动画时间,在动画中需要用到。
沙漏翻转
.hourglass {
position: relative;
width: 120px;
height: 200px;
margin: 0 auto;
animation: rotate var(--rotateTime) linear infinite;
transform-origin: center 100px;
}
@keyframes rotate {
0% {
transform: rotate(0deg);
}
45% {
transform: rotate(0deg);
}
50% {
transform: rotate(180deg);
}
99% {
transform: rotate(180deg);
}
100% {
transform: rotate(360deg);
}
}
计时结束(沙漏沙子漏完)后需要将整个沙漏框架翻转,在rotateTime时间内沙漏需要翻转2次,也就是说沙漏漏完一次的时间是rotateTime。
沙堆减少和增加
.sand-top {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 90px;
background-color: #f5d76e;
clip-path: polygon(0 0, 100% 0, 51% 100%, 49% 100%);
border-top-left-radius: 10px;
border-top-right-radius: 10px;
animation: sand-top var(--rotateTime) linear infinite;
}
.sand-bottom {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 0;
background-color: #f5d76e;
clip-path: polygon(49% 0, 51% 0, 100% 100%, 0 100%);
animation: sand-bottom var(--rotateTime) linear infinite;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
/* 上半部分沙子减少动画 */
@keyframes sand-top {
0% {
height: 90px;
width: 100%;
}
49% {
height: 0;
width: 0;
left: 50%;
top: 90px;
}
50% {
height: 0px;
width: 100%;
top: 0;
left: 0;
}
99% {
width: 100%;
height: 90px;
}
100% {
width: 100%;
height: 90px;
}
}
/* 下半部分沙子增加动画 */
@keyframes sand-bottom {
0% {
height: 0;
width: 100%;
bottom: 0;
left: 0;
}
50% {
height: 90px;
width: 100%;
bottom: 0;
left: 0;
}
51% {
height: 90px;
width: 100%;
bottom: 0;
left: 0;
}
99% {
height: 0px;
width: 0;
bottom: 90px;
left: 50%;
}
100% {
height: 0px;
width: 0;
bottom: 90px;
left: 50%;
}
}
上半部分沙堆需要先减少后增加,下半部分沙堆需要先增加后减少;通过改变高度、宽度和位置,模拟沙子流动的过程。
管道沙子滴落
@keyframes sand-drop {
0% {
opacity: 1;
transform: translate(-50%, 0);
}
4.9%,
9.9%,
14.9%,
……,
44.9%,
49.9% {
opacity: 0;
transform: translate(-50%, 15px);
}
5%,
10%,
15%,
……,
40%,
45% {
opacity: 0;
transform: translate(-50%, 0);
}
5.1%,
10.1%,
……,
90.1%,
95.1% {
opacity: 1;
}
50%,
55%,
……,
100% {
opacity: 0;
transform: translate(-50%, -15px);
}
54.9%,
59.9%,
64.9%,
……,
94.9%,
99.9% {
opacity: 0;
transform: translate(-50%, -30px);
}
}
通过控制透明度和位移,模拟沙子滴落的连贯动作,每5%的动画时间完成一个滴落动作,以10s为例的话也就是每0.5s完成一个滴落动作;因为沙子漏完之后整个沙漏需要翻转180°,所以沙子滴落的动画应该分为前后两段,前半段是从上往下滴( transform: translate(-50%, 15px) ),后半段是从下往上滴( transform: translate(-50%, -15px) )。
源码
gitee
github
- 🌟 觉得有帮助的可以点个 star~
- 🖊 有什么问题或错误可以指出,欢迎 pr~
- 📬 有什么想要实现的功能或想法可以联系我~
公众号
关注公众号『 前端也能这么有趣 』,获取更多有趣内容。
发送 加群 还可以加入群聊,一起来学习(摸鱼)吧~
说在后面
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『
前端也能这么有趣
』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。