目录

实现思路

具体实现

基础html

背景颜色

容器颜色

水样式

两个水波样式

完整代码

总结


 

实现思路

  • 先实现一个装水的容器,可以通过box-shadow给容器增添点厚度的感觉

  • 水的实现,其实就是一个纯色的背景

  • 接下来就是波纹的实现

  • 思考下现有的css属性可以有这样的效果吗?

  • 答案是否定的,那我们怎样通过dom+css来实现这样的效果呢?

  • 我们可以看到波纹的行动轨迹是有规律的,再仔细观察后会发现其实每四个小周期是一个循环,每四个小周期之后的动画都是固定的

    • 那其实可以通过赛贝尔曲线+animation来实现
    • 当然,这就比较复杂了,赛贝尔曲线+animation的方案其实是可以实现任意n个小周期为一个循环的
  • 那还能通过怎样的方式来实现这样的运动轨迹呢?

    • 先观察圆形容器中的浅粉色部分,会发现其实他就是一个带有border-radius的正方形在旋转,或者是一个长于宽相差不大的矩形

      • 也就是通过border-raduis+animation即可
    • 再观察浅粉色和深蓝色中间的浅蓝色部分的移动轨迹,已经有了一次推测的大家应该也可以很快发现,其实这也是一个带有border-radius的正方形或长宽相差不大的矩形,只不过这个的border-radius更大而已

    • 因为更大,所以看上去转动时波动就没那么明显

    • 然后水dom在最下面,浅蓝色dom在中间,浅粉色dom在最上面,这样颜色互相覆盖之下,就能形成类似的视觉效果

  • 上面提到转动的是正方形或长于宽相差不大的矩形,这是为什么呢?

    • 因为假设一下,长宽相差比较明显,这时一个矩形的转动还是挺有规律的,但是如果是两个矩形转动呢?
    • 我们要的是有波纹效果,也就是其中一个矩形在转动时永远比另一个矩形转动时稍大,这样才会相差一部分看着像波纹
  • 还有一个没那么重要但是也需要注意的点

    • 我们可以看到,认真观察的话,其实他们旋转都不是正对圆心的,也就是要更偏一点的,这个是为了让两个带圆角的正方形旋转时不要总是间隔一致,要有错落有致的感觉

      • 所以也需要设置translate
      • 又因为做旋转动画时需要用到transform:rotate(0deg)transform:rotate(360deg)的旋转
      • 所以是transform: translate(-50%, -60%) rotate(0deg)transform: translate(-50%, -60%) rotate(360deg)
      • 当然,两个水波dom的translate属性可以适当偏差一点,但是不宜偏差过大,因为过大之后还是会出现上面说过的长宽相距太大时会出现的问题

下面完整代码来反过来分析

具体实现

基础html

<div class="TheCircle">
  <div class="Water"></div>
</div>

我们只关注背景和容器,因为.water可以设置两个伪元素,所以就用伪元素来代替两个水波

背景颜色

body {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: rgb(240, 228, 228);
}

背景最好要是浅色的,这样看起来跟水与水波的对比才会更清晰

容器颜色

.TheCircle {
  position: relative;
  width: 180px;
  height: 180px;
  border-radius: 50%;
  border: 3px solid rgb(246, 247, 248);
  box-shadow: 0 0 0 3px rgb(41, 134, 196);
}

因为后续要基于该容器定位,所以是relative

水样式

.Water {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgb(23, 106, 201);
  border-radius: 50%;
  overflow: hidden;
}

水既是深蓝色背景,也要起到容器的作用,添加overflow:hidden来保证实现水波的两个dom不会超出,当然,这个样式写在容器上也可以

两个水波样式

.Water::after {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 150%;
  height: 150%;
  border-radius: 40%;
  background-color: rgb(240, 228, 228);
  animation: real 5s linear infinite;
}
​
@keyframes real {
  0% {
    transform: translate(-50%, -65%) rotate(0deg);
  }
​
  100% {
    transform: translate(-50%, -65%) rotate(360deg);
  }
}
​
.Water::before {
  content: '';
  position: absolute;
  top: 0;
  left: 50%;
  width: 150%;
  height: 150%;
  border-radius: 42%;
  background-color: rgb(240, 228, 228, 0.2);
  animation: virtual 7s linear infinite;
}
​
@keyframes virtual {
  0% {
    transform: translate(-50%, -60%) rotate(0deg);
  }
​
  100% {
    transform: translate(-50%, -60%) rotate(360deg);
  }
}

可以看到两个水波domtranslateborder-radius都有少许的不同,这个可以根据实现视觉效果微调

完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>雾里有果橙</title>
</head>
<body>
    <div class="TheCircle">
        <div class="Water"></div>
    </div>
</body>
</html>
* {
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

body {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: rgb(240, 228, 228);
}

.TheCircle {
    position: relative;
    width: 180px;
    height: 180px;
    border-radius: 50%;
    border: 3px solid rgb(246, 247, 248);
    box-shadow: 0 0 0 3px rgb(41, 134, 196);
}

.Water {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgb(23, 106, 201);
    border-radius: 50%;
    overflow: hidden;
}

.Water::after {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    width: 150%;
    height: 150%;
    border-radius: 40%;
    background-color: rgb(240, 228, 228);
    animation: real 5s linear infinite;
}

@keyframes real {
    0% {
        transform: translate(-50%, -65%) rotate(0deg);
    }

    100% {
        transform: translate(-50%, -65%) rotate(360deg);
    }
}

.Water::before {
    content: '';
    position: absolute;
    top: 0;
    left: 50%;
    width: 150%;
    height: 150%;
    border-radius: 42%;
    background-color: rgb(240, 228, 228, 0.2);
    animation: virtual 7s linear infinite;
}

@keyframes virtual {
    0% {
        transform: translate(-50%, -60%) rotate(0deg);
    }

    100% {
        transform: translate(-50%, -60%) rotate(360deg);
    }
}

总结

  • 重点是两个水波dom的动画相互配合
  • 当然还可以有更多水波dom,这完全取决于自己
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐