纯css实现波浪效果

原理

原理十分简单,我们都知道,一个正方形,给它添加 border-radius: 50%,将会得到一个圆形。

  • border-radius:用来设置边框圆角,当使用一个半径时确定一个圆形。
    好的,如果 border-radius 没到 50%,但是接近 50% ,我们会得到一个这样的图形: 注意边角,整个图形给人的感觉是有点圆,却不是很圆。额,这不是废话吗 ?

好的,那整这么个图形又有什么用?还能变出波浪来不成?

没错!就是这么神奇。:)
我们让上面这个图形滚动起来(rotate) ,看看效果:

可能很多人看到这里还没懂旋转起来的意图,仔细盯着一边看,是会有类似波浪的起伏效果的。

而我们的目的,就是要借助这个动态变换的起伏动画,模拟制造出类似波浪的效果。

实现

当然,这里看到是全景实现图,所以感觉并不明显,OK,让我们用一个个例子看看具体实现起来能达到什么样的效果。

我们利用上面原理可以做到的一种波浪运动背景效果图:

后面漂浮的波浪效果,其实就是利用了上面的 border-radius: 45% 的椭圆形,只是放大了很多倍,视野之外的图形都 overflow: hidden ,只留下了一条边的视野,并且增加了一些相应的transform 变换。

  • 注意,这里背景是蓝色静止的,运动是白色的椭圆形。
    代码也很简单,CSS 代码如下:
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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
:root{
--dispaly:flex;
--justify:center;
--align:center;
--backgroundColor: #FF0099;
--backgroundColor1: rgb(118, 218, 255);
--backgroundColor2: #fff;
--borderRadius: 40%;
--animation: rotate 6s linear infinite;
}
.comCenter{
display: var(--dispaly);
justify-content:var(--justify);
align-items: var(--align);
}
.topBox div{
width: 140px;
height: 140px;
background: var(--backgroundColor);
border-radius:var(--borderRadius);
margin: 60px;
animation: var(--animation);
}
@keyframes rotate{
0%{
transform:translate(-30%, -70%) rotate(0deg);
}
50%{
transform:translate(-40%, -73%) rotate(180deg);
}
100%{
transform:translate(-30%, -70%) rotate(360deg);
}
}
.centerBox .aa{
position: relative;
width: 220px;
min-height: 220px;
background: var(--backgroundColor1);
overflow: hidden;
}
.centerBox .aa:before{
content:'';
position: absolute;
left: 50%;
min-width: 140px;
min-height: 140px;
background: var(--backgroundColor2);
animation: var(--animation);
}
.centerBox .aa:after{
content:'';
position: absolute;
left: 50%;
min-width: 140px;
min-height: 140px;
background: var(--backgroundColor2);
animation: var(--animation);
}
.centerBox .aa:before{
bottom: 30px;
border-radius: 45%;
}
.centerBox .aa:after{
bottom: 22px;
opacity: .5;
border-radius: 47%;
}

可能有部分同学,还存在疑问,OK,那我们把上面的效果缩小 10 倍,将视野之外的动画也补齐,那么其实生成波浪的原理是这样的:

图中的虚线框就是我们实际的视野范围。
值得注意的是,要看到,这里我们生成波浪,并不是利用旋转的椭圆本身,而是利用它去切割背景,产生波浪的效果。那为什么不直接使用旋转的椭圆本身模拟波浪效果呢?因为:

  • 中间高,两边低的效果不符合物理学原理,看上去十分别扭;

    使用纯 CSS 实现波浪进度图

    好,既然掌握了这种方法,下面我们就使用纯 CSS 实现上面最开始使用 SVG 或者 CANVAS 才能实现的波浪进度图。

HTML 结构如下:

<div class="container">
    <div class="wave"></div>
</div>

CSS 代码如下:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
:root{
--dispaly:flex;
--justify:center;
--align:center;
--backgroundColor: #FF0099;
--backgroundColor1: rgb(118, 218, 255);
--backgroundColor2: #fff;
--borderRadius: 40%;
--animation: rotate 6s linear infinite;
}
.waveBox{
width: 210px;
height: 210px;
--borderRadius:50%;
border-radius: var(--borderRadius);
border: 5px solid var(--backgroundColor1);
z-index: 30;
overflow: hidden;
}
.wave{
width: 200px;
height: 200px;
background:var(--backgroundColor1);
position: relative;
--borderRadius:50%;
border-radius: var(--borderRadius);
overflow: hidden;
}
.wave:after{
content: '';
position: absolute;
width:400px;
height: 400px;
top:0;
left:20%;
--animation: rotate 7s linear -5s infinite;
animation: var(--animation);
}
.wave:before{
content: '';
position: absolute;
width:400px;
height: 400px;
top:0;
left:20%;
background: rgba(255, 255, 255, .4);
border-radius: 35%;
z-index: 10;
animation: var(--animation);
}
.wave:after{
border-radius: 37%;
background: rgba(255,255,255,.9);
z-index: 20;
}
@keyframes rotate{
0%{
transform:translate(-30%, -70%) rotate(0deg);
}
50%{
transform:translate(-40%, -73%) rotate(180deg);
}
100%{
transform:translate(-30%, -70%) rotate(360deg);
}
}

效果图:

虽然效果差了一点点,但是相较于要使用学习成本更高的 SVG 或者 CANVAS,这种纯 CSS 方法无疑可使用的场景更多,学习成本更低!

一些小技巧

单纯的让一个 border-radius 接近 50 的椭圆形旋转,动画效果可能不是那么逼真,我们可以适当的添加一些其他变换因素,让动画效果看上去更真实:

  • 在动画过程中,动态的改变 border-radius 的值;
  • 在动画过程中,利用 transform 对旋转椭圆进行轻微的位移、变形;
  • 上面也演示到了,多个椭圆同时转动,赋予不同时长的动画,并且添加轻微的透明度,让整个效果更佳逼真。