david2tdw / blog

学习记录
1 stars 1 forks source link

[CSS] 充电动画 #137

Open david2tdw opened 4 years ago

david2tdw commented 4 years ago

巧用 CSS 实现酷炫的充电动画

david2tdw commented 4 years ago

简易版:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>充电动画</title>
    <style>
      html,
      body {
        width: 100%;
        height: 100%;
        display: flex;
        background: #e4e4e4;
      }
      .container {
        position: relative;
        width: 140px;
        margin: auto;
      }
      .battery {
        height: 220px;
        box-sizing: border-box;
        border-radius: 15px 15px 5px 5px; /* 左上 右上 右下 左下 */
        background-color: #fff;
        z-index: 1;
      }
      /* 电池头部 */
      .battery::before {
        content: '';
        position: absolute;
        width: 26px;
        height: 10px;
        left: 50%;
        top: 0;
        transform: translate(-50%, -10px);
        border-radius: 5px 5px 0 0;
        background: rgba(240, 240, 240, 0.88);
      }
      /* 电池内部充电颜色变换 */
      .battery::after {
        content: '';
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0; /* 距离battery底部的距离 */
        top: 90%; /* 距离battery顶部的距离 */
        background: linear-gradient(to bottom, #7abcff 0%, #00bcd4 44%, #2196f3 100%); /* 从顶部到底部 */
        border-radius: 0 0 5px 5px;
        box-shadow: 0 14px 28px rgba(33, 150, 243, 0), 0 10px 10px rgba(9, 188, 215, 0.08); /* 水平阴影 垂直阴影 */
        animation: charging 10s linear infinite;
        filter: hue-rotate(90deg); /* 使用 filter: hue-rotate() 对渐变色彩进行色彩过渡变换动画 */
      }
      /* 电池内部充电波浪范围 */
      .battery-copy {
        position: absolute;
        top: 0;
        left: 0;
        width: 140px;
        height: 220px;
        border-radius: 15px 15px 5px 5px; /* 左上 右上 右下 左下 */
        overflow: hidden; /* 隐藏波浪外部内容 */
      }
      /* 电池内部充电波浪 */
      .wave {
        position: absolute;
        bottom: 25px;
        left: 50%;
        transform: translate(-50%, 0);
        width: 300px;
        height: 300px;
        background: rgba(255, 255, 255, 0.8);
        border-radius: 45% 47% 44% 42%;
        animation: move 10s linear infinite;
        /* z-index: 1; */

      }
      .wave:nth-child(2) {
        border-radius: 38% 46% 43% 47%;
        transform: translate(-50%, 0) rotate(-135deg);
      }
      .wave:nth-child(3) {
        border-radius: 42% 46% 37% 40%;
        transform: translate(-50%, 0) rotate(135deg); /* 偏移指定像素,并旋转指定角度 */
      }
      @keyframes charging {
        /* 控制.battery::after 里的属性变化 */
        50% {
          box-shadow: 0 14px 28px rgba(0, 150, 136, 0.83), 0px 4px 10px rgba(9, 188, 215, 0.4);
        }
        95% {
          top: 5%;
          filter: hue-rotate(0deg);
          border-radius: 0 0 5px 5px;
          box-shadow: 0 14px 28px rgba(4, 188, 213, 0.2), 0 10px 10px rgba(9, 188, 215, 0.08);
        }
        100% {
          top: 0%;
          filter: hue-rotate(0deg);
          border-radius: 15px 15px 5px 5px;
        }
      }
      @keyframes move {
        100% {
          transform: translate(-50%, -160px) rotate(720deg);
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="battery"></div>
      <div class="battery-copy">
        <div class="wave"></div>
        <div class="wave"></div>
        <div class="wave"></div>
      </div>
    </div>
  </body>
</html>
david2tdw commented 4 years ago

高级版:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>安卓充电动画</title>
    <style>
      html,
      body {
        display: flex;
        width: 100%;
        height: 100%;
        background-color: #000;
        overflow: hidden;
      }
      .container {
        position: relative;
        width: 300px;
        height: 400px;
        margin: auto;
      }
      .number {
        position: absolute;
        top: 27%;
        width: 300px;
        text-align: center;
        font-size: 32px;
        z-index: 10;
        color: #fff;
      }
      .constract {
        filter: contrast(15) hue-rotate(0);
        width: 300px;
        height: 400px;
        background-color: #000;
        overflow: hidden;
        animation: hueRotate 10s linear infinite;
      }
      .circle {
        position: relative;
        width: 300px;
        height: 300px;
        box-sizing: border-box;
        filter: blur(8px);
      }
      .circle::after {
        content: '';
        position: absolute;
        top: 40%;
        left: 50%;
        transform: translate(-50%, -50%) rotate(0);
        width: 200px;
        height: 200px;
        background-color: #00ff6f;
        border-radius: 42% 38% 62% 49% / 45%;
        animation: rotate 10s linear infinite;
      }
      .circle::before {
        content: '';
        position: absolute;
        top: 40%;
        left: 50%;
        width: 176px;
        height: 176px;
        transform: translate(-50%, -50%);
        border-radius: 50%;
        background-color: #000;
        z-index: 10;
      }
      .bubbles {
        position: absolute;
        left: 50%;
        bottom: 0;
        width: 100px;
        height: 40px;
        transform: translate(-50%, 0);
        border-radius: 100px 100px 0 0;
        background-color: #00ff6f;
        filter: blur(5px); /* blur()结合contrast()生成融合效果 */
      }
      li {
        position: absolute;
        border-radius: 50%;
        background-color: #00ff6f;
      }
      li:nth-child(0) {
        left: 51px; /* 调整气泡位置 */
        top: 50%;
        transform: translate(-50%, -50%);
        height: 22px; /* 调整气泡大小 */
        width: 22px; /* 调整气泡大小 */
        animation: moveToTop 9s ease-in-out -0.25s infinite; /* 调整运动时间 设置延迟时间 */
      }
      li:nth-child(1) {
        left: 71px;
        top: 50%;
        transform: translate(-35%, -50%);
        height: 36px;
        width: 36px;
        animation: moveToTop 3s ease-in-out -4.25s infinite;
      }
      li:nth-child(2) {
        left: 55px;
        top: 50%;
        transform: translate(-50%, -50%);
        height: 12px;
        width: 12px;
        animation: moveToTop 6s ease-in-out -0.21s infinite;
      }
      li:nth-child(3) {
        left: 61px;
        top: 50%;
        transform: translate(-50%, -50%);
        height: 32px;
        width: 32px;
        animation: moveToTop 4s ease-in-out -2.25s infinite;
      }
      /* contrast:调整图像的对比度。*/
      /* hue-rotate 内部包含元素颜色变化 */
      @keyframes hueRotate {
        100% {
          filter: contrast(15) hue-rotate(360deg);
        }
      }
      @keyframes rotate {
        50% {
          border-radius: 45% / 42% 38% 58% 49%;
        }
        100% {
          transform: translate(-50%, -50%) rotate(720deg); /* 转2圈 */
        }
      }
      @keyframes moveToTop {
        90% {
          opacity: 1;
        }
        100% {
          opacity: 0.1; /* 融合后自然消失,不是突然消失 */
          transform: translate(-50%, -180px);
        }
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="number">98.7%</div>
      <div class="constract">
        <div class="circle"></div>
        <ul class="bubbles">
          <li></li>
          <li></li>
          <li></li>
          <li></li>
        </ul>
      </div>
    </div>
  </body>
</html>