前言
👏CSS 圆锥渐变+MASK遮罩实现WIFI图标,速速来Get吧~
🥇文末分享源代码。记得点赞+关注+收藏!
1.实现效果
2.实现步骤
- 定义css变量–bg背景色,–dot弧宽度,–w父元素宽度,–gap,各弧度之间的间距
:root {
--bg: #fff;
--dot: 20px;
--w: 300px;
--gap: 45px;
}
- 定义父元素container
<div class="container"></div>
.container {
width: var(--w);
position: relative;
border: 1px solid red;
}
- 父元素内添加一个子元素line
<div class="container">
+ <div class="line" ></div>
</div>
- 设置line样式为absolute定位,设置宽高为–w,圆角50%,背景设置圆锥渐变,–bg占据35%,剩下为透明色;
conic-gradient():
CSS 函数 conic-gradient() 创建了一个由渐变组成的图像,渐变的颜色变换围绕一个中心点旋转(而不是从中心辐射)。锥形渐变的例子包括饼图和色轮 color wheels (en-US). conic-gradient() 函数的结果是 gradient 数据类型的对象,是一种特殊的 image 数据类型。
.line{
position: absolute;
width: var(--w);
height: var(--w);
border-radius: 50%;
background: conic-gradient(var(--bg) 35%, transparent 35%);
}
- 为line设置mask遮罩,弧形宽度为–dot,那么渐变的值则为父元素宽度的一半(–w/2)减去dot
.line{
-webkit-mask: radial-gradient(
transparent calc(var(--w) / 2 - var(--dot) - 1px),
#000 calc(var(--w) / 2 - var(--dot))
);
}
- 为line添加前后伪元素,居于圆的正中间,宽高为dot,圆角50%,背景色为–bg;
.line::before,
.line::after {
content: "";
position: absolute;
width: var(--dot);
height: var(--dot);
border-radius: 50%;
left: calc(var(--w) / 2 - var(--dot) / 2);
top: calc(var(--w) / 2 - var(--dot) / 2);
background: var(--bg);
}
- mask遮罩的存在,使得伪元素不可见,通过调试可以看到相应的位置;
- 调整前伪元素的位置,使其移动到圆弧的最上方
.line::before {
transform: translate(0, calc(var(--dot) / 2 - var(--w) / 2));
}
- 调整后伪元素的位置,使其移动到圆弧的最下方
.line::after {
transform: rotate(calc(360deg * 0.35))
translate(0, calc(var(--dot) / 2 - var(--w) / 2));
}
- 将line元素整体旋转60deg,就得到一个完整的圆弧了
.line{
transform: rotate(-60deg);
}
- 接下来,我们实现剩余圆弧以及中间圆点
- 再次定义两个line元素
<div class="container">
<div class="line" ></div>
+ <div class="line" ></div>
+ <div class="line" ></div>
</div>
- 根据gap,动态修改圆弧的宽度,并设置定位,可以参考CSS 实现七彩圆环loading动画
- 第一,第二圆环宽度
- 第三个圆环宽度
- 可以得到,每个圆环的宽度为calc(var(–w) - var(–gap) * 2 * var(–i)),i为当前圆环的索引位置(从0开始,依次+1)
- 为line元素设置行内css变量–i
<div class="container">
<div class="line" style="--i: 0"></div>
<div class="line" style="--i: 1"></div>
<div class="line" style="--i: 2"></div>
</div>
- 修改line元素的宽高,将相关的–w替换为–width
.line {
--width: calc(var(--w) - var(--gap) * 2 * var(--i));
width: var(--width);
height: var(--width);
-webkit-mask: radial-gradient(
transparent calc(var(--width) / 2 - var(--dot) - 1px),
#000 calc(var(--width) / 2 - var(--dot))
);
}
.line::before,
.line::after {
left: calc(var(--width) / 2 - var(--dot) / 2);
top: calc(var(--width) / 2 - var(--dot) / 2); *
}
.line::before {
transform: translate(0, calc(var(--dot) / 2 - var(--width) / 2));
}
.line::after {
transform: rotate(calc(360deg * 0.35))
translate(0, calc(var(--dot) / 2 - var(--width) / 2));
}
- 为每个半圆环(line元素)设置top,第一个圆环为0,第二个为gap,第三个为gap*2,可得到top为 calc(var(–gap) * var(–i)),并水平居中
.line{
/* 水平居中 */
left: calc(50% - var(--width) / 2);
/* 距离顶部的距离,根据gap来定 */
top: calc(var(--gap) * var(--i));
}
- 父元素内添加dot元素,宽高为dot,背景色为–bg,圆角50%,水平居中,top为第一个圆环的位置即为calc(var(–gap) * 3)
<div class="container">
+ <div class="dot"></div>
</div>
.dot {
position: absolute;
width: var(--dot);
height: var(--dot);
border-radius: 50%;
top: calc(var(--gap) * 3);
background: var(--bg);
left: calc(50% - var(--dot) / 2);
}
- 设置父元素的高度为calc(var(–gap) * 3 + var(–dot))
.container {
+ height: calc(var(--gap) * 3 + var(--dot));
}
- 去掉父元素辅助线条,就完成啦~
3.实现代码
<style>
:root {
--bg: #fff;
--dot: 20px;
--w: 300px;
--gap: 45px;
}
.container {
width: var(--w);
height: calc(var(--gap) * 3 + var(--dot));
position: relative;
}
.line {
position: absolute;
--width: calc(var(--w) - var(--gap) * 2 * var(--i));
width: var(--width);
height: var(--width);
/* 水平居中 */
left: calc(50% - var(--width) / 2);
/* 距离顶部的距离,根据gap来定 */
top: calc(var(--gap) * var(--i));
border-radius: 50%;
background: conic-gradient(var(--bg) 35%, transparent 35%);
-webkit-mask: radial-gradient(
transparent calc(var(--width) / 2 - var(--dot) - 1px),
#000 calc(var(--width) / 2 - var(--dot))
);
transform: rotate(-60deg);
}
.line::before,
.line::after {
content: "";
position: absolute;
width: var(--dot);
height: var(--dot);
border-radius: 50%;
left: calc(var(--width) / 2 - var(--dot) / 2);
top: calc(var(--width) / 2 - var(--dot) / 2);
background: var(--bg);
}
.line::before {
transform: translate(0, calc(var(--dot) / 2 - var(--width) / 2));
}
.line::after {
transform: rotate(calc(360deg * 0.35))
translate(0, calc(var(--dot) / 2 - var(--width) / 2));
}
.dot {
position: absolute;
width: var(--dot);
height: var(--dot);
border-radius: 50%;
top: calc(var(--gap) * 3);
background: var(--bg);
left: calc(50% - var(--dot) / 2);
}
</style>
<body>
<div class="container">
<div class="line" style="--i: 0"></div>
<div class="line" style="--i: 1"></div>
<div class="line" style="--i: 2"></div>
<div class="dot"></div>
</div>
</body>