关于前端:别用图片了CSS遮罩合成实现带圆角的环形loading动画

46次阅读

共计 4379 个字符,预计需要花费 11 分钟才能阅读完成。

欢送关注我的公众号:前端侦探

明天来用 CSS 实现一个带圆角的环形 loading 动画,成果是这样的

先不思考动画,其实就是这样一个图形

那么,如何来绘制呢?上面花两分钟一起看看吧

一、CSS 实现思路

首先,看到这环形逐步隐没的成果,也就是透明度突变的成果,必定要联想到 锥形突变

conic-gradient() – CSS:层叠样式表 | MDN (mozilla.org)

通过锥形突变,能够很轻松的实现这样一个成果,通明到纯色的突变

loading{background: conic-gradient(transparent 10%, royalblue 90%)
}

成果如下

而后,整体是一个环形,能够通过径向突变配合 mask 遮罩实现

radial-gradient() – CSS:层叠样式表 | MDN (mozilla.org)

mask – CSS: Cascading Style Sheets | MDN (mozilla.org)

loading{
  /*...*/
  -webkit-mask: radial-gradient(closest-side circle, transparent 50%, red 51% 99%, transparent 100%);
}

原理是这样的

还有一个圆角,能够间接用径向突变实现

loading{background: radial-gradient( closest-side circle, royalblue 99%, transparent 100%) center top/25% 25% no-repeat,
  conic-gradient(transparent 10%, royalblue 90%);;
}

其实就是两个雷同色彩的突变叠加到一起造成的,如下

所以残缺代码就是

loading{
    width: 200px;
    height: 200px;
    background: 
    radial-gradient(closest-side circle, royalblue 99%, transparent 100%) center top/25% 25% no-repeat,
    conic-gradient(transparent 10%, royalblue 90%);
    -webkit-mask: radial-gradient(closest-side circle, transparent 50%, red 51% 99%, transparent 100%);
}

二、更好地自定义色彩

下面的实现尽管很好的满足了需要,然而,还是有些 CSS 设计问题。

比方,我如果须要扭转 loading 的色彩,须要扭转 两个 中央

很显著,这样的实现不太合乎 DRY(Don’t Repeat Yourself)准则。

有一个比较简单思路能够用 CSS 变量来传递

loading{
    --color: royalblue;
    background: 
    radial-gradient(closest-side circle, var(--color) 99%, transparent 100%) center top/25% 25% no-repeat,
    conic-gradient(transparent 10%, var(--color) 90%);
    -webkit-mask: radial-gradient(closest-side circle, transparent 50%, red 51% 99%, transparent 100%);
}

这样每次都只须要扭转一个变量就行了。

loading.red{--color: red;}

除了这种形式以外,其实还有一点须要思考,为啥背景不能洁净一点、纯正一点呢?换个说法,当初的背景实现对于不理解的同学来讲,可能会很吃力,是否将这些细节暗藏起来,更直观地去自定义色彩呢?比方像这种形式

loading.red{background: red;}

如果要实现这样的成果,就须要将绘制局部全副在 mask 遮罩中实现,背景只是展现而已。

那么,如何通过 mask 遮罩实现这样的图形呢?

三、更直观地去自定义色彩

mask遮罩其实也和 CSS 背景差不多,只是多了一些图形合成操作,其实就是布尔运算,也就是mask-composite

mask-composite – CSS: Cascading Style Sheets | MDN (mozilla.org)

/* Keyword values */
mask-composite: add; /* 叠加(默认)*/
mask-composite: subtract; /* 减去,排除掉下层的区域 */
mask-composite: intersect; /* 相交,只显示重合的中央 */
mask-composite: exclude; /* 排除,只显示不重合的中央 */

置信在很多图形设计软件中都见到相似的操作(上面是 photoshop)

这个属性的值(规范和非标准)十分多,-webkit-mask-composite 与规范下的值有所不同,属性值十分多,如下(chorme、safari 反对)

-webkit-mask-composite: clear; /* 革除,不显示任何遮罩 */
-webkit-mask-composite: copy; /* 只显示上方遮罩,不显示下方遮罩 */
-webkit-mask-composite: source-over; /* 叠加,两者都显示 */
-webkit-mask-composite: source-in; /* 只显示重合的中央 */
-webkit-mask-composite: source-out; /* 只显示上方遮罩,重合的中央不显示 */
-webkit-mask-composite: source-atop;
-webkit-mask-composite: destination-over; /* 叠加,两者都显示 */
-webkit-mask-composite: destination-in; /* 只显示重合的中央 */
-webkit-mask-composite: destination-out;/* 只显示下方遮罩,重合的中央不显示 */
-webkit-mask-composite: destination-atop;
-webkit-mask-composite: xor; /* 只显示不重合的中央 */

之前在这篇文章中有具体介绍 mask-composite 的用法,有趣味的能够回顾一下

CSS mask 实现鼠标追随镂空成果

回到这里,思考一下🤔,怎么来绘制这样一个图形?

形态是一样的,只是和后面的步骤略微有些差别

首先还是绘制环形突变,能够先绘制锥形突变和环形突变,如下

loading{
    background: royalblue;
    -webkit-mask: 
    radial-gradient(closest-side circle, transparent 49%, red 50% 99%, transparent 100%),
    conic-gradient(transparent 10%, royalblue 90%);
}

然而这样两个突变会叠加在一起

其实咱们须要是只显示两者重叠的局部,也就是穿插区域,这个个性在 mask-composite 中对应的就是 destination-in 或者source-in

loading{
  ...
  -webkit-mask-composite: source-in;
}

成果如下

而后是那个圆角,和下面绘制一样

loading{
  ...
  -webkit-mask: 
    radial-gradient(closest-side circle, royalblue 99%, transparent 100%) center top/25% 25% no-repeat,
    radial-gradient(closest-side circle, transparent 49%, red 50% 99%, transparent 100%),
    conic-gradient(transparent 10%, royalblue 90%)
    ;
  -webkit-mask-composite: source-in;
}

如果间接这样叠加,会变成这样

其实这是因为 source-in 导致的,三个图形,最初只显示了三者重叠的区域。然而咱们当初须要的是最下面的圆角间接叠加就行了,不须要裁剪,能够用到source-over

loading{-webkit-mask-composite: source-over, source-in;}

成果如下

上面是残缺代码

loading{
    width: 200px;
    height: 200px;
    background: royalblue;
    -webkit-mask: 
    radial-gradient(closest-side circle, royalblue 99%, transparent 100%) center top/25% 25% no-repeat,
    radial-gradient(closest-side circle, transparent 49%, red 50% 99%, transparent 100%),
    conic-gradient(transparent 10%, royalblue 90%);
    -webkit-mask-composite: source-over, source-in;
}

如果要换色彩,间接更换背景就能够了,还能够是突变

loading{background: conic-gradient(red, orange, red)
}

自定义色彩起来是不是更加直观?

四、动画和安利

动画很简略,就是一个有限旋转的线性动画,这个没什么好说的

loading{animation: rotate 1s linear infinite;}
@keyframes rotate{
  to{transform: rotate(360deg); 
  }
}

这样就实现了文章结尾成果

对于线上 demo,这里安利一下我开发的 xy-ui 组件库(目前正在重构中 …),外面 loading 组件就用到了这个实现

https://xy-ui.codelabo.cn

很多乏味的 CSS 小技巧都能够在这个组件库中找到,欢送 star & fork 👏🏻👏🏻👏🏻

五、总结和阐明

以上就是本文的全部内容了,稍显啰嗦,不过也是为了提供更多的思路,上面总结一下实现重点

  1. 整个实现其实用到了锥形突变和径向突变
  2. 失常思路是背景绘制出通明锥形突变,而后通过 mask 遮罩裁剪出环形
  3. 不过这种思路改色彩略微麻烦一点,能够通过 CSS 变量传递,简化代码
  4. 色彩在背景中不够直观,能够思考将实现细节放到 mask 中
  5. mask 遮罩合成能够实现图形的合成与裁剪,能够更灵便的布尔运算
  6. 举荐一下我的组件库 xy-ui,能够学到更多乏味的 CSS 小技巧

最初,如果感觉还不错,对你有帮忙的话,欢送点赞、珍藏、转发❤❤❤,同时也欢送喜爱 CSS 的各位关注我,加我微信XboxYan,一起交换,共同进步。

欢送关注我的公众号:前端侦探

正文完
 0