2022-01-19

巧用 CSS 实现动态线条 Loading 动画

有群友问我,使用 CSS 如何实现如下 Loading 效果:

这是一个非常有意思的问题。

我们知道,使用 CSS,我们可以非常轻松的实现这样一个动画效果:

<div></div>  
div {   width: 100px;   height: 100px;   border-radius: 50%;   border: 2px solid transparent;   border-top: 2px solid #000;   border-left: 2px solid #000;   animation: rotate 3s infinite linear;  }  @keyframes rotate {   100% {    transform: rotate(360deg);   }  }  

动画如下:

与要求的线条 loading 动画相比,上述动画缺少了比较核心的一点在于:

  • 线条在旋转运动的过程中,长短是会发生变化的

所以,这里的的难点也就转变为了,如何动态的实现弧形线段的长短变化?解决了这个问题,也就基本上解决了上述的线条变换 Loading 动画。

本文将介绍 CSS 当中,几种有意思的,可能可以动态改变弧形线条长短的方式:

方法一:使用遮罩实现

第一种方法,也是比较容易想到的方式,使用遮罩的方式实现。

我们实现两个半圆线条,一个是实际能看到的颜色,另外一个则是和背景色相同的,相对更为粗一点的半圆线条,当两条线条运动的速率不一致时,我们从视觉上,也就能看到动态变化的弧形线条。

看看示意图,一看就懂:

我们把上述红色线条,替换成背景白色,整体的动画效果就非常的相似了,伪代码如下:

<div></div>  
  div {   width: 200px;   height: 200px;  }  div::before {   position: absolute;   content: "";   top: 0px; left: 0px; right: 0px; bottom: 0px;   border-radius: 50%;   border: 3px solid transparent;   border-top: 3px solid #000;   border-left: 3px solid #000;   animation: rotate 3s infinite ease-out;  }  div::after {   position: absolute;   content: "";   top: -2px; left: -2px; right: -2px; bottom: -2px;   border-radius: 50%;   border: 7px solid transparent;   border-bottom: 7px solid #fff;   border-right: 7px solid #fff;   animation: rotate 4s infinite ease-in-out;  }  @keyframes rotate {   100% {    transform: rotate(0deg);   }  }  

核心就是实现两条半圆线条,一条黑色,一条背景色,两段线条以不同的速率运动(通过动画时间及缓动控制),效果如下:

完整的代码你可以猛击 -- CodePen Demo - Linear Loading

上述方案最大的 2 个问题在于:

  1. 如果背景色不是纯色,会露馅
  2. 如果要求能展现的线段长度大于半个圆,无法完成

基于此,我们只能另辟蹊径。

方法二:借助 SVG 的 stroke-* 能力

在之前非常多的篇文章中,都有讲到过在 CSS 配合 SVG,我们可以实现各种简单或复杂的线条动画,像是简单的:

或者自定义复杂路径的复杂的线条动画:

> 对 CSS/SVG 实现线条动画感兴趣的,但是还不太了解的,可以看看我的这篇文章 -- 【Web动画】SVG 线条动画入门

在这里,我们只需要一个简单的 SVG 标签 <circle>,配合其 CSS 样式 stroke-dasharraystroke-dashoffset 即可轻松完成上述效果:

<svg viewbox="25 25 50 50">   <circle cx="50" cy="50" r="20" fill="none" />  </svg>  
.circular {   width: 100px;   height: 100px;   animation: rotate 2s linear infinite;  }  ..path {   stroke-dasharray: 1, 200;   stroke-dashoffset: 0;   stroke: #000;   animation: dash 1.5s ease-in-out infinite  }  @keyframes rotate {   100% {   transform: rotate(360deg);   }  }  @keyframes dash {   0% {   stroke-dasharray: 1, 200;   stroke-dashoffset: 0;   }   50% {   stroke-dasharray: 89, 200;   stroke-dashoffset: -35px;   }   100% {   stroke-dasharray: 89, 200;   stroke-dashoffset: -124px;   }  }  

简单解释下:

  • stroke:类比 css 中的 border-color,给 svg 图形设定边框颜色;
  • stroke-dasharray:值是一组数组,没数量上限,每个数字交替表示划线与间隔的宽度;
  • stroke-dashoffset:dash 模式到路径开始的距离。

我们利用 stroke-dasharray 将原本完整的线条切割成多段,假设是 stroke-dasharray: 10, 10 表示这样一个图形:

No comments:

Post a Comment