笔记:SVG 环形动画(进度条)原理


 拍摄于 2017-06-26。
拍摄于 2017-06-26。

第一步,圆形的 SVG shape - <circle>

CodePen 链接
  1. SVG 中基本的形状(basis shape)有 circleellipselineploygonpolylinerect,环形进度条的展示在这里使用的是 circle;
  2. SVG 使用 x, y, width, height 来定义自身在页面上的 viewport,配合 viewbox 属性,来对内部子元素的单位进行计算,以上面 circle 为例,( svg 的 viewport 中 width / viewbox 中的 width )等于 200 / 200 = 1,这里是故意设置,不等于 1 的情况比比皆是,而且需要明确这里 1 是不带单位,是一个计算出的比例值1;
  3. circle 元素上的 cxcy 属性分别指定 circle 的位置,r 代表 circle 的半径距离,例子中外层的 svg 的 widthheight 都是 200,circle 的 cxcy 都是 100 所以 circle 正好居中,同时 r 半径为 80;
  4. strokestroke-width 分别代表描边颜色和描边粗细,fill 代表 circle 整个的填充色, 例子中为无。

第二步,描边点状化

CodePen 链接
  1. stroke-dasharray 属性,可以将图形的描边进行「点状化」,这里需要理解的是,「点状化」的「点」,其大小是可以设置的,并不真的就是那么一个「·」,可以变长或者变短。上面例子中的三个 circle 分别设置 stroke-dasharray 为 10,50,100;
  2. 所以如果 circle 的点的长度正好等于 circle 边长,那么「点」看上去就是 circle 的边。

第三步,动起来(使用 stroke-dashoffset 抵消一个长度很长的「点」)

CodePen 链接
  1. stroke-dashoffset 可以使上一步中使用 stroke-dasharray 生成的「点」沿着 path 移动;
  2. 想象一个足够长的「点」+ 足够长的「offset」。比如 stroke-dashoffset 设置成 1000,元素的描边就不会显示,上面的例子中,三个 circle 的 stroke-dasharray 分别为 100,500,1000,stroke-dashoffset 都是 1000,配合 animation 从 1000 运动到 0;
  3. circle 描边的「起始位置」在 circle 在 3 点钟方向,使用 transform: rotate() 逆时针旋转 90 度使「起始位置」定位到 12 点方向。

第四步,根据半径计算周长

auto animation

CodePen 链接

control stroke-dashoffset using JavaScript

CodePen 链接 作为底部占位符的圆,使用另外一个描边变淡变细的 <circle> 元素(希望可以找到更优、比如不需要多加元素的方案)。
第一步提到 <circle> 会自带一个 r 的属性,指定当前 circle 的半径,2 * r * Math.PI 可以得到 <circle> 的周长,这个周长,代表了我们需要 stroke-dasharray 代表的「点」的长度,同时也是也是 stroke-dashoffset 的值,长度相互抵消,视觉上就看不到这个「点」。
同时 JavaScript 的控制的时候,应使用 el.style.storkeDash = val 的方式,而不是 el.setAttribute(),分别写作 el.style.strokeDasharrayel.style.strokeDashoffsetarrayaoffseto 都不需要大写。
  1. 为了配合 CSS 中 transition 中的各种 easing 效果,不要直接在 <circle> 元素上设置 stroke-dasharraystorke-dashoffset,以 CSS 中对应的值代替。
  2. 同时 JavaScript 的控制的时候,应使用 el.style.storkeDash = val 的方式,而不是 el.setAttribute(),分别写作 el.style.strokeDasharrayel.style.strokeDashoffsetarrayaoffseto 都不需要大写。
  3. 同时由于 offset 值是通过 JavaScript 计算得到,考虑通过 JavaScript 设置元素的 transition 值,避免 page load 的过程中元素发生动画;或者 CSS 默认给一个绝对大的值。
  1. 第四部第二个根据 input[range] 来演示的例子中,input 的值从 0 到 100 变化,step 是 1, stroke-dashoffset 对应的变化的值的公式就是 len - (range_value / 100) * len

参考、以及衍生阅读

  1. How SVG Line Animation Works
  2. SVG 快速入门
  3. SVG 动画精髓
  4. SVG Stroke , Marker 以及 CSS

感谢阅读

你们好, 2018 年初把小站从 Jekyll 迁移到 Hugo 的过程中,删除了评论区放的 Disqus 插件,考虑有二:首先无论评论、还是对笔记内容的进一步讨论,读者们更喜欢通过邮件、或者 Twitter 私信的方式来沟通;其次一年多以来 Disqus 后台能看到几乎都是垃圾留言(spam),所以这里直接贴一下邮件、以及 Twitter 账户 地址。

技术发展迭代很快,所以这些笔记内容也有类似新闻的时效性,不免有过时、或者错误的地方,欢迎指正 ^_^。

BEST
Lien(A.K.A 胡椒)
本站总访问量 本站总访客量 本文总阅读量