布景

最近在工作中遇到一个水球进度条,用svg制作几个波涛叠加动画写起来超简单,6哇~

文末共享源代码。记得点赞+重视+收藏!

1.完结作用

css3动画+svg完结水球进度条

2.完结原理

2.1 边框圆角突变色

  • 咱们都知道,完结一个边框突变色能够用border-image,可是border-image不支持圆角

border-image:

border-image CSS 特点答应在元素的边框上制作图画。这使得制作复杂的外观组件愈加简单,也不用在某些情况下使用九宫格了。

使用 border-image 时,其将会替换掉border-style 特点所设置的边框款式。

css3动画+svg完结水球进度条

  div{
    width: 200px;
    height: 80px;
    border: 2px solid;
    border-image: linear-gradient(180deg, red, orange) 1;
  }
  • 完结边框圆角 突变的方法蛮多的,这里说一下background-clip吧(缺点:内容布景无法透明)~

background-clip: 规定布景的制作区域

语法:

background-clip: border-box|padding-box|content-box;
描绘
border-box 布景被裁剪到边框盒
padding-box 布景被裁剪到内边距框
content-box 布景被裁剪到内容框

background-origin:

background-Origin特点指定background-position特点应该是相对方位。

留意如果布景图画background-attachment是”固定”,这个特点没有任何作用。

语法:

background-origin: padding-box|border-box|content-box;
描绘
border-box 布景图画边界框的相对方位
padding-box 布景图画填充框的相对方位
content-box 布景图画的相对方位的内容框

css3动画+svg完结水球进度条

  div {
    width: 100px;
    height: 100px;
    border: 2px solid transparent;
    background-image: linear-gradient(var(--bg), var(--bg)),
      linear-gradient(180deg, red, orange);
    /* 前一个为内容布景色,后边为边框突变色 */
    background-origin: border-box;
    background-clip: content-box, border-box;
    border-radius: 0px;
    animation: 2s toBorder linear infinite alternate;
  }
  @keyframes toBorder {
    100% {
      border-radius: 50%;
    }
  }

2.2 svg完结波涛

2.2.1 SVG是什么

SVG:可缩放矢量图形

可缩放矢量图形(Scalable Vector Graphics,SVG)依据 XML 标记言语,用于描绘二维的矢量图形。

作为一个依据文本的敞开网络规范,SVG 能够优雅而简洁地烘托不同大小的图形,并和CSS、DOM、JavaScript 和 SMIL 等其他网络规范无缝衔接。

本质上,SVG 相对于图画,就好比 HTML 相对于文本。

和传统的点阵图画形式(如 JPEG 和 PNG)不同的是,SVG 格式供给的是矢量图,这意味着它的图画能够被无限扩大而不失真或降低质量,而且能够方便地修改内容,无需图形编辑器。经过使用适宜的库进行配合,SVG 文件甚至能够随时进行本地化。

兼容性

css3动画+svg完结水球进度条

2.2.2 SVG特点

  • version: 用于指明 SVG 文档遵从规范。它只答应在根元素svg 上使用。它纯粹是一个说明,对烘托或处理没有任何影响,尽管它承受任何数字,可是只有1.0 和 1.1.这两个有用的挑选。
  • 命名空间:
xmlns:http://www.w3.org/2000/svg 固定值
xmlns:xlink:http://www.w3.org/1999/xlink 固定值
xml:space:preserve 固定值
  • class:款式名称
  • width | height: 界说 svg 画布的大小
  • viewbox: viewBox 特点答应指定一个给定的一组图形扩展以习惯特定的容器元素。viewBox 特点的值是一个包括 4 个参数的列表 min-x, min-y, width and height,以空格或许逗号分离隔,在用户空间中指定一个矩形区域映射到给定的元素。 width 或许 height 的值,小于或等于 0 的情况下,这个元素将不会被烘托出来。

2.2.3 SVG途径

path元素是 SVG根本形状中最强壮的一个。

你能够用它创立线条,曲线,弧形等等。

path 只需要设定很少的点,就能够创立滑润流畅的线条(比如曲线)。

尽管polyline元素也能完结相似的作用,可是必须设置很多的点(点越密布,越挨近连续,看起来越滑润流畅),而且这种做法不能够扩大(扩大后,点的离散更明显)

path 标签用来界说途径,path 元素的形状是经过特点d界说的,特点d的值是一个“指令 + 参数”的序列

下面的指令可用于途径数据:(所有指令均可小写。大写表明肯定定位,小写表明相对定位)

M = moveto
L = lineto
H = horizontal lineto
V = vertical lineto
C = curveto
S = smooth curveto
Q = quadratic Belzier curve
T = smooth quadratic Belzier curveto
A = elliptical Arc
Z = closepath
2.2.3.1 凭借一些东西来协助咱们进行制作

1.在线制作svg波涛:getwaves.io/

css3动画+svg完结水球进度条

2.在线制作svg波涛:fffuel.co/sssurf/

css3动画+svg完结水球进度条

3.在线制作svg波涛:svgwave.in/

css3动画+svg完结水球进度条

在线查看svg:c.runoob.com/more/svgedi…

css3动画+svg完结水球进度条

2.2.3.2 制作波涛
  • 能够凭借一些专业东西来完结svg的制作

css3动画+svg完结水球进度条

 <svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 600 140" class="box-waves">
   <path d="M 0 70 Q 75 20,150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z">
    </path>
  </svg>
  • 在class款式中为其增加填充色彩,fill相当于css中的background;stroke相当于 css 中的 border-color。

css3动画+svg完结水球进度条

div{
	 fill: #a0edff;
	 stroke: orange;
}

2.3 波涛动摇动画

  • 制作三个一模一样的波涛,设置不同的填充色,经过absolute定位在相同方位。
  • 设置不同的x轴方向的偏移量,不同的z-index层级,使波涛参差分布。

css3动画+svg完结水球进度条

  • 增加动画,x偏移量变化,波涛1与波涛3设置x偏移由-50%—>0%,经过不同的动画时间,使得分布错乱。
  • 波涛2设置x偏移量由0%—>-50%。

css3动画+svg完结水球进度条

svg:nth-child(1) {
  fill: #a0edff;
   transform: translate(-50%, 0);
   z-index: 3;
   animation: wave-move1 1.5s linear infinite;
 }
svg:nth-child(2) {
  fill: rgba(40, 187, 255, 0.5);
   transform: translate(0, 0);
   z-index: 2;
   animation: wave-move2 3s linear infinite;
 }
svg:nth-child(3) {
  fill: #2084cc;
   transform: translate(-50%, 0);
   z-index: 1;
   animation: wave-move1 3s linear infinite;
 }
@keyframes wave-move1 {
   100% {
     transform: translate(0, 0);
   }
 }
 @keyframes wave-move2 {
   100% {
     transform: translate(-50%, 0);
   }
 }

3.完结步骤

3.1 根本款式

  • 画一个边框突变的圆环,为外圆

css3动画+svg完结水球进度条

<div class="box-inner"></div>
 .box-inner {
   width: 200px;
   height: 200px;
   box-shadow: 0px 2px 7px 0px #238fdb;
   border-radius: 50%;
   position: relative;
   border: 2px solid transparent;
   background-image: linear-gradient(#021f40, #021f40),
     linear-gradient(180deg, rgba(36, 144, 220, 0.41), rgba(37, 147, 225, 1));
   background-origin: border-box;
   background-clip: content-box, border-box;
  /* overflow: hidden; 溢出隐藏 */
 }
  • 外圆内画一个圆,依据外圆absolute定位,left为0,bottom为0,为内圆;

css3动画+svg完结水球进度条

<div class="box-inner">
	<div class="inner"></div>
</div>
  .inner {
    position: relative;
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    bottom: -128%;
    background-color: #a0edff;
  }
  • 内圆内制作三个svg波涛,依据内圆absolute定位,left为0,bottom为100%,坐落内圆的最上方。因为要对其进行x方向的50%进行偏移,将svg的大小设置为该内圆宽度的2倍

css3动画+svg完结水球进度条

  • 重新设置内圆的bottom距离,假定现在设置为-70%,看看是啥样的

css3动画+svg完结水球进度条

  • 设置外圆溢出隐藏,overflow:hidden,能够看出水球由下半部的正方形+上半部分的svg波涛组成

css3动画+svg完结水球进度条

  • 两者连接处能够看见一条明显的线条,咱们能够经过对波涛1设置margin-bottom:-2px来处理

css3动画+svg完结水球进度条

  • 依照上述2.3节所述,加上动摇动画,有点容貌了,6哇

css3动画+svg完结水球进度条

3.2 依照百分比展示

  • 首页,改动内圆的bottom方位,咱们试着将内圆移出外圆所见规模(调试过程中,将外圆的溢出先去掉)

css3动画+svg完结水球进度条

  • 将内圆bottom改完-128%(具体数值依据你制作的svg宽高决议,可自行调试),即可将内圆移出外圆所见规模,试想一下,百分之0的时分,内圆不行见
  • 当百分比改动的时分,0%对应bottom为-128%,10%对应为-128+10=118%;50%对应-128+50=78%;依次类推可得到一个公式:
bottom数值=calc(-128% + 当时百分比)
  • 或许咱们不改动bottom数值,对该内圆进行y方向向上的偏移,0%对应偏移量为0,10%对应-10%,50%对应-50%;依次类推可得到一个公式:
transform数值=translateY(calc(0% - 当时百分比));
  • 为内圆设置行内款式,界说var变量表明当时百分比
    css3动画+svg完结水球进度条
 <div class="inner" style="--per:50%" id="box"></div>
.inner {
   width: 100%;
   height: 100%;
   position: absolute;
   left: 0;
   background-color: #a0edff;
   /* 直接对bottom操作 */
   bottom: calc(-128% + var(--per));
   /* 或许y方向偏移
   transform: translateY(calc(0% - var(--per)));*/
 }

4.完结代码

<div class="box flex-row j_c">
  <div class="box-inner">
     <div class="inner" style="--per:0%" id="box">
       <svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 600 140" class="box-waves">
         <path d="M 0 70 Q 75 20,150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z">
         </path>
       </svg>
       <svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 600 140" class="box-waves">
         <path d="M 0 70 Q 75 20,150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z">
         </path>
       </svg>
       <svg xmlns="http://www.w3.org/2000/svg" version="1.0" viewBox="0 0 600 140" class="box-waves">
         <path d="M 0 70 Q 75 20,150 70 T 300 70 T 450 70 T 600 70 L 600 140 L 0 140 L 0 70Z">
         </path>
       </svg>
     </div>
   </div>
   <div id="percentText" class="box-text">--%</div>
 </div>
:root {
    --bg: #222;
    --wave1: #a0edff;
    --wave2: rgba(40, 187, 255, 0.5);
    --wave3: #2084cc;
  }
  body {
    background: var(--bg);
  }
  .box {
    width: 650px;
    height: 300px;
    background: linear-gradient(270deg,
        rgba(29, 170, 210, 0) 0%,
        rgba(29, 170, 210, 0.1) 13%,
        rgba(29, 170, 210, 0.4) 49%,
        rgba(29, 170, 210, 0.1) 84%,
        rgba(29, 170, 210, 0) 100%);
    border: 1px solid;
    border-image: linear-gradient(270deg,
        rgba(81, 201, 232, 0),
        rgba(56, 187, 222, 1),
        rgba(30, 172, 212, 0)) 1 1;
    margin-bottom: 120px;
  }
  .box-inner {
    width: 200px;
    height: 200px;
    box-shadow: 0px 2px 7px 0px #238fdb;
    border-radius: 50%;
    position: relative;
    border: 2px solid transparent;
    background-image: linear-gradient(#021f40, #021f40),
      linear-gradient(180deg, rgba(36, 144, 220, 0.41), rgba(37, 147, 225, 1));
    background-origin: border-box;
    background-clip: content-box, border-box;
    overflow: hidden;
  }
  .inner {
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    background: #a0edff;
    /* 直接对bottom操作 */
    bottom: calc(-128% + var(--per));
  }
  .box-waves {
    position: absolute;
    left: 0;
    bottom: 100%;
    width: 200%;
    stroke: none;
  }
  .box-waves:nth-child(1) {
    fill: var(--wave1);
    transform: translate(-50%, 0);
    z-index: 3;
    animation: wave-move1 1.5s linear infinite;
    /* svg重合有一条线 */
    margin-bottom: -2px;
  }
  .box-waves:nth-child(2) {
    fill: var(--wave2);
    transform: translate(0, 0);
    z-index: 2;
    animation: wave-move2 3s linear infinite;
  }
  .box-waves:nth-child(3) {
    fill: var(--wave3);
    transform: translate(-50%, 0);
    z-index: 1;
    animation: wave-move1 3s linear infinite;
  }
  @keyframes wave-move1 {
    100% {
      transform: translate(0, 0);
    }
  }
  @keyframes wave-move2 {
    100% {
      transform: translate(-50%, 0);
    }
  }
  .box-text {
    font-size: 30px;
    font-weight: bold;
    width: 80px;
    margin-left: 20px;
    text-align: center;
    color: #7EEDFF;
  }
const getData = () => {
 const box = document.getElementById('box');
 const text = document.getElementById('percentText');
 let i = 0;
 let timer = null;
 const loading = () => {
   if (i < 100) {
     i++;
     box.style.setProperty('--per', i + '%'); // 设置CSS变量
     text.innerHTML = i + '%';
   } else {
     i = 0;
     clearInterval(timer);
     setTimeout(() => {
       text.innerHTML = '0%';
       box.style.setProperty('--per', '0%'); // 设置CSS变量
       timer = setInterval(loading, 1000);
     }, 2000);
   }
 }
 loading();
 timer = setInterval(loading, 1000);
}
getData();

5.写在最后

看完本文如果觉得对你有一丢丢协助,记得点赞+重视+收藏鸭
更多相关内容,重视苏苏的bug,苏苏的github,苏苏的码云~