前言

  最近在学习前端知识,在做背景的时候想弄一个椭圆的弧形,想到以前网上看到的水波效果,开始制作一个水波动画,在制作的过程中也遇到一些问题,最终也找到了答案,也算是查漏补缺了。

设计思路

  一个有颜色的圆形作为背景(海水的颜色),一个有透明度的白色的圆润的正方形作为挡板1,一个白色的的圆润的正方形作为挡板2。
  挡板的作用是“推动海水形成波浪”,波浪的弧度跟挡板的边角比有关x,下面挡板的图片,正方形里面圆形的才是挡板,圆形外面蓝色的是因为挡板有透明度,为了直观感受背景和挡板的颜色而色设置成蓝色的。

圆形背景(海水)白色透明挡板1(浅色圆形),透明度为0.4白色透明挡板2(浅色圆形),透明度为0.9
海水在这里插入图片描述挡板2

  由于挡板有透明度,所以挡板1是浅蓝色,挡板2不是纯白色的,是由于透明度低而显得白,其实挡板2是浅浅浅非常浅的浅蓝色。
  挡板的半径是要比背景的半径要大的,这里的比例我设置成了2:1。
  CSS在设置border-radius时当边角比小于50%时,边的中间是直线而不是弧,边长不变的情况下边角比越小直线越明显,边角比不变的情况下边越长直线越明显。

边长200px的正方形,边角比为45%边长200px的正方形,边角比为35%
边角比45%边角比35%
边长400px的正方形,边角比为45%边长400px的正方形,边角比为35%
在这里插入图片描述在这里插入图片描述

图例

  把上述形状组合成一起后:
组合1
  别看他小小的,其实不是这样的,当我给挡板加上边框后:
在这里插入图片描述

  当我给挡板加上动画,两个挡板滚动起来,就出现了波浪动画:

动画有框的动画
动画有边框的动画

完整代码

  代码参考自:纯css实现波浪动画,超级简单

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Pure CSS Wave</title>
	<style>
        .container {
            position: relative;
            margin: 20% auto;
            padding: 0;
            border: 0;
            width: 200px;
            height: 200px;
            background-color: rgb(118, 218, 255); 
            border-radius: 50%;
        }
        .wave0,.wave1{
            position: absolute;
            width: 400px;
            height: 400px;
            margin-top: -150%;
            margin-left: -50%;
            background-color: rgba(255, 255, 255, .4);
            border-radius: 45%;
            animation: spin 15s linear -0s infinite;
            z-index: 10;
/*            border: 1px solid;*/
        }
        .wave1{
            margin-top: -152%;
            background-color: rgba(255, 255, 255, .9);
            border-radius: 47%;
            animation: spin 30s linear -15s infinite;
            z-index: 20;
        }
        @keyframes spin{
            0%{
                transform: translate(-0%, -0%) rotate(0deg) scale(1);
            }
            25%{
                transform: translate(-1%, -1%) rotate(90deg) scale(1.0);
            }
            50%{
                transform: translate(-0%, -2%) rotate(180deg) scale(1.0);
            }
            75%{
                transform: translate(1%, -1%) rotate(270deg) scale(1.0);
            }
            100%{
                transform: translate(-0%, -0%) rotate(360deg) scale(1.0);
            }
        }
	</style>
</head>
<body>
	<div class="container">
	    <div class="wave0"></div>
	    <div class="wave1"></div>
	</div>
</body>
</html>

细节&问题

1. 双伪元素

  • 利用双伪元素变成两个挡板,这时就不需要像上面代码那样在<div class="container">里放置两个<div>了,只需要一个div标签<div class="container"></div>,CSS代码如下:
.container::before,.container::after{
	content: "";/*content 属性与::before及::after配合使用*/
	position: absolute;
	...
}

  content和position这两个属性是缺一不可的,content: "";即没有内容的伪元素,把它类比成<div></div>
  这时的伪元素还不显示,把他们设置成position: absolute;后就出现了,由于::before和::after默认为行内元素,行内元素无法设置宽度高度,宽度只与内容有关,而前面content: "";导致伪元素没有内容,position: absolute;就把它们强制变成块级元素,相当于display:block;,这时就可以对伪元素设置宽高了。
  至于双伪元素为啥可以重合,是position: absolute;的关系,两个div时也是一样,而一个div后面(或者前面)跟着一个伪元素after或before时,div和伪元素之间是有间隔的,代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	<style>
        .wave1{
            position: absolute;
            width: 200px;
            height: 200px;
            border: 1px solid;
        }
        .wave1::after{
            content: "";
            position: absolute;
            width: 200px;
            height: 200px;
/*
            left: -1px;
            top: -1px;
*/
            border: 1px solid;
        }
	</style>
</head>
<body>
	    <div class="wave1"></div>
</body>
</html>

  如图所示,div和伪元素是不完全重合的,边框过粗:
div和伪元素不重合
  利用top和left对伪元素位置进行调整left: -1px; top: -1px;之后就显示正常了,如图:
正常重合
  另外,双伪元素还可以用来清除浮动;

2.CSS并集选择器

  在声明各种CSS选择器时,如果某些选择器的风格完全相同,或者部分相同,便可以利用并集选择器同时声明这些风格相同的CSS选择器。
  上面的.wave0,.wave1{...}.container::before,.container::after{...}用的正是并集选择器的风格,声明并初始化wave0、wave1、container::before、container::after

2.position

  关于position:relative和position:absolute,可以看菜鸟教程 CSS position 相对定位和绝对定位

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐