写在前面
笔者最近面试恰好碰到此题,以往做这类的需求往往都是问设计师要两张呼吸前后的图片,更或者直接GIF完事,真要开始纯用CSS3的一时半会摸不着头脑,于是乎自己准备认真撸上一发按钮呼吸,看看有什么幺蛾子。 首先先看别人家的预览图,咱们得照着做一个:
第一眼分析:
- 中间白圈内若隐若现
- 两边白圈成波纹铺开
1.第一步,先找到一张箭头图
笔者去阿里font白嫖了一张~
为了比较好看出效果,采取了透明底图片,dom元素深色背景。如下
2.开始造圈圈
<div id="breath-btn">
<div id="inner" class="white-border">
<img class="arrow" src="./arrow.png" />
</div>
</div>
html, body {
height: 100vh;
background: #0078db;
}
#breath-btn {
width: 80px;
height: 80px;
position: relative;
display: inline-block;
margin: auto 50%;
margin-top: 200px;
display: flex;
justify-content: center;
align-items: center;
}
.white-border{
border: 2px solid #fff;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 50px;
}
.arrow {
width: 70%;
}
差不多整体布局出来了
3.中间白圈内若隐若现
通过写个动画@keyframes来定义
#inner {
animation: OpacityBreath 2s ease-in-out infinite;
opacity: 0.3;
}
@keyframes OpacityBreath {
0% {
opacity: 0.3;
}
50% {
opacity: 0.65;
}
100% {
opacity: 0.3;
}
}
看起来像回事,先暂定如此。
4.创造波纹
重头戏来了。通过慢放仔细观察,发现外圈率先弹出,但是内圈速度更快。至于做法采用transform的scale把圈子扩大,同时加上透明度变化。外层的波纹都用伪类来做节省dom元素,活用伪类真方便。
#breath-btn::before,
#breath-btn::after {
content: '';
border: 2px solid #fff;
width: 50px;
height: 50px;
position: absolute;
opacity: 0;
border-radius: 50%;
}
@keyframes Wave {
0% {
transform: scale(1);
opacity: 0.3;
}
100% {
transform: scale(2);
opacity: 0;
}
}
5.波纹动起来。
看到这里想让波纹动起来应该没啥难度吧,笔者当时也这么想。不假思索的写下以下样式
#breath-btn::before {
animation: Wave 1.1s ease-in-out infinite;
}
#breath-btn::after {
animation: Wave 0.7s ease-in-out 0.4s infinite;
}
最外层的圈设置1.1s走完,内层速度要快0.7s,0.4s延迟时间,造成视觉上的追击感。但是问题来了,animation的delay time只有第一次生效,这真的是坑爹啊,第一次追击成功后面整个就是乱套,真希望CSS能把这个属性在补强一点。于是乎笔者最后采用脚本解决:
.breath-btn-animation::before {
animation: Wave 1.1s ease-in-out;
}
.breath-btn-animation::after {
animation: Wave 0.7s ease-in-out 0.4s;
}
<body>
<div id="breath-btn">
<div id="inner" class="white-border">
<img class="arrow" src="./arrow.png" />
</div>
</div>
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
function toggleWave() {
$('#breath-btn').toggleClass('breath-btn-animation');
setTimeout(() => {
toggleWave()
}, 1800)
}
toggleWave();
</script>
</body>
通过jquery动态切换breath-btn-animation,让两层波纹圈跳动一次,再设置延迟时间,最终效果如下:
最终效果相差无几,需要调整的就是动画时间和曲线算法了。
总结
开发小小的一个按钮呼吸态,不禁感叹CSS是真神奇,开发途中还遇到一个transform-origin的问题导致更改了布局采用了伪类,这个放到下期再研究吧。
ps(掘金的富文本编辑太难用了,复制代码一定要纯文本粘贴,不然换行符GG)